默认排序顺序为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