請幫我處理串列 我有一個串列名稱
arr = [{'name':'cator3'}
{'name':'cator1'}
{'name':'CATOR5 (Active A)'},
{'name':'cator17'},
{'name':'cator12'},
{'name':'cator4'},
{'name':'CATOR5 (Passive A)'},
{'name':'cator23'},
{'name':'cator2'}]
每個字典都有一個包含字符和數字的名稱。我處理了排序,我有結果
我的代碼:
def sort_order_by(e):
order_by = 'name'
return e[order_by].lower()
sort='asc'
if sort == 'asc':
arr.sort(key=sort_order_by)
elif sort == 'desc':
arr.sort(key=sort_order_by, reverse=True)
print(arr)
我的結果:
result = [{'name': 'cator1'},
{'name': 'cator12'},
{'name': 'cator17'},
{'name': 'cator2'},
{'name': 'cator23'},
{'name': 'cator3'},
{'name': 'cator4'},
{'name': 'CATOR5 (Active A)'},
{'name': 'CATOR5 (Passive A)'}]
您可以在初始文本后看到數字之間的錯誤排列:
cator1、cator12、cator17、cator2、cator23、cator3 ...
但是 2 < 3 < 12 < 17 < 23
我希望數字和字母有正確的結果
我期望的結果將按字母和數字順序排列
expected = [{'name': 'cator1'},
{'name': 'cator2'},
{'name': 'cator3'},
{'name': 'cator4'},
{'name': 'CATOR5 (Active A)'},
{'name': 'CATOR5 (Passive A)'},
{'name': 'cator12'},
{'name': 'cator17'},
{'name': 'cator23'},]
如何獲得正確的排序順序?
uj5u.com熱心網友回復:
如果您可以使用外部庫,我強烈推薦natsort. 一旦你運行pip install natsort或conda install natsort或等效,你可以做
from natsort import natsorted, ns
arr = natsorted(arr, alg=ns.IGNORECASE, reverse=sort == 'desc')
如果您想要就地排序,您可以生成一個排序鍵并將其用于arr.sort:
from natsort import natsort_keygen, ns
arr.sort(key=natsort_keygen(alg=ns.IGNORECASE), reverse=sort == 'desc')
免責宣告:我不是 natsort 的作者,也不是它的附屬機構。盡管有一次我確實修復了檔案中的一個小錯字。
uj5u.com熱心網友回復:
下面是一個簡短的演示示例,它逐步完成了一個程序。值得注意的是,這是一個任意的排序規范,并沒有試圖太聰明。
它還假定字串的長度為 5,后跟一個數字。如果您愿意,您可以執行正則運算式或類似程序(或文字迭代)來識別字串。您還可以更高級并建立更一般的關系(盡管聽起來您并不關心這一點)。
arr=[
{'name':'cator3'},
{'name':'cator1'},
{'name':'CATOR5 (Active A)'},
{'name':'cator17'},
{'name':'cator12'},
{'name':'cator4'},
{'name':'CATOR5 (Passive A)'},
{'name':'cator23'},
{'name':'cator2'}
]
def sort_order_by(e):
order_by = 'name'
key = e[order_by].lower() ; print(key, "->", end=' ')
split = key.split()
rest = ' '.join(split[1:])
key = split[0] ; print(key, "->", end=' ')
key, nkey = key[:5], key[5:] ; print(key, nkey, "->", end=' ')
nkey = f"{int(nkey):05}" ; print(key nkey rest)
return key nkey rest
sort_type = 'asc'
arr.sort(key=sort_order_by, reverse=(sort_type == 'desc'))
[print(x) for x in arr]
輸出:
cator3 -> cator3 -> cator 3 -> cator00003
cator1 -> cator1 -> cator 1 -> cator00001
cator5 (active a) -> cator5 -> cator 5 -> cator00005(active a)
cator17 -> cator17 -> cator 17 -> cator00017
cator12 -> cator12 -> cator 12 -> cator00012
cator4 -> cator4 -> cator 4 -> cator00004
cator5 (passive a) -> cator5 -> cator 5 -> cator00005(passive a)
cator23 -> cator23 -> cator 23 -> cator00023
cator2 -> cator2 -> cator 2 -> cator00002
{'name': 'cator1'}
{'name': 'cator2'}
{'name': 'cator3'}
{'name': 'cator4'}
{'name': 'CATOR5 (Active A)'}
{'name': 'CATOR5 (Passive A)'}
{'name': 'cator12'}
{'name': 'cator17'}
{'name': 'cator23'}
uj5u.com熱心網友回復:
您可以使用正則運算式替換來右對齊長度為 10 的字串的數字部分。這將使它們在字串的字母數字順序內正確排序(按數字順序)。
這可以使用 lambda 作為 re.sub() 中的替換值來實作:
arr = [{'name':'cator3'},
{'name':'cator1'},
{'name':'CATOR5 (Active A)'},
{'name':'cator17'},
{'name':'cator12'},
{'name':'cator4'},
{'name':'CATOR5 (Passive A)'},
{'name':'cator23'},
{'name':'cator2'}]
import re
arr.sort(key=lambda d: re.sub(r'\d*',
lambda n: f"{n.group():>10}",
d['name'].lower()))
print(*arr,sep='\n')
{'name': 'cator1'}
{'name': 'cator2'}
{'name': 'cator3'}
{'name': 'cator4'}
{'name': 'CATOR5 (Active A)'}
{'name': 'CATOR5 (Passive A)'}
{'name': 'cator12'}
{'name': 'cator17'}
{'name': 'cator23'}
如果您要經常在不同的字典串列上執行此操作和/或使用不同的鍵,則可以為其創建一個實用程式函式:
import re
def alpha_num(k):
return lambda d: re.sub(r'\d*',lambda n: f"{n.group():>10}",d[k].lower())
arr.sort(key=alpha_num('name'))
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/324615.html
上一篇:go中的包排序影響所有切片
