默認排序順序爲ASCII字符串從Python的sorted
功能lexicographic(或 'ASCIIbetical'):
>>> li=['1', '20', '100', '11']
>>> sorted(li)
['1', '100', '11', '20']
相比時,這些列表值是整數整數大小:
>>> sorted(map(int, li))
[1, 11, 20, 100]
即,人眼的字符串數量的大小與計算機眼睛的相同字符串的大小不同。 (寫在Codinghorror更廣泛)
要解決它,我們需要從數字中分離字母,並將數字轉換爲整數(或浮點數)。
最簡單的方法是用正則表達式捕獲所有數字,然後轉換爲整數,然後轉換爲所有字母。
此排序到你的目標:
li1='''\
01AA01
01AS01
01NA01
01BA01
01MA01
01AA02
01AS02
02BA01'''.splitlines()
tgt='''\
01AA01
01AS01
01BA01
01MA01
01NA01
01AA02
01AS02
02BA01'''.splitlines()
import re
def kf(s):
nums=map(int, re.findall(r'(\d+)', s))
lets=re.findall(r'([a-zA-Z]+)', s)
return nums+lets
print tgt==sorted(li1, key=kf)
# True
或者一個行:
>>> tgt==sorted(li1, key=lambda s: map(int, re.findall(r'(\d+)', s))+re.findall(r'(\D+)', s))
True
編輯基於評論
的問題狀態的文本 :
我希望它在首節01,02,03 ...... 數字進行排序,然後按字母順序爲AA,AS,BA在第二部分,並且 數值再次爲第三部分。
但是,示例表明情況並非如此。
我們可以排序的基礎上(INT,字母,INT)與拆分模式:
>>> [re.split(r'(\D+)', e) for e in li1]
[['01', 'AA', '01'], ['01', 'AS', '01'], ['01', 'NA', '01'], ['01', 'BA', '01'], ['01', 'MA', '01'], ['01', 'AA', '02'], ['01', 'AS', '02'], ['02', 'BA', '01']]
>>> sorted(li1, key=lambda s: [int(e) if e.isdigit() else e for e in re.split(r'(\D+)', s)])
['01AA01', '01AA02', '01AS01', '01AS02', '01BA01', '01MA01', '01NA01', '02BA01']
# ^^ ^^ etc '01AA02', before '01AS01' in the example
通過檢查,張貼的例子的模式是(int, int, letters)
可以在這裏看到:
>>> [map(int, re.findall(r'(\d+)', s))+re.findall(r'(\D+)', s) for s in li1]
[[1, 1, 'AA'], [1, 1, 'AS'], [1, 1, 'NA'], [1, 1, 'BA'], [1, 1, 'MA'], [1, 2, 'AA'], [1, 2, 'AS'], [2, 1, 'BA']]
如果TEXT是正確的,使用排序的分割形式我有;如果例是正確的,使用nums+lets
形式。
就像一個註釋,如果所有的列值看起來像那樣,那麼排序將保持你想要的順序。例如,對該列進行排序會自動滿足您的所有條件。因此,您可以簡化您的問題以按列對CSV進行排序,因爲這裏不需要特殊的排序條件。 – Tommy 2014-09-22 01:42:19
@Tommy - 我不明白...你是說因爲樣本已經按OP的方式排序,所以它們都必須按照這種方式排序? – tdelaney 2014-09-22 01:47:35
@Tammy,你用什麼工具管理csv,csv模塊?當你想排序時它是在一個python列表中嗎? – tdelaney 2014-09-22 01:48:32