2011-05-11 92 views
58

可能重复:
Does Python have a built in function for string natural sort?如何正确地用一个数字对一个字符串进行排序?

我有一个包含数字的字符串列表,我找不到对它们进行排序的好方法。
比如我得到的是这样的:

something1 
something12 
something17 
something2 
something25 
something29 

sort()方法。

我知道我可能需要以某种方式提取数字,然后对列表进行排序,但我不知道如何以最简单的方式进行排序。

+0

sort()有什么问题? – tMC 2011-05-11 16:24:20

+5

这有一个名称,自然分类。请参阅http://stackoverflow.com/questions/2545532/python-analog-of-natsort-function-sort-a-list-using-a-natural-order-algorithm和http://stackoverflow.com/questions/4836710/does-python-have-a-built-in-function-for-string-natural-sort和其他人。 – 2011-05-11 16:24:43

+0

我不知道它有一个名字,我的坏名字。谢谢。 – Michal 2011-05-11 16:37:32

回答

117

也许你正在寻找human sorting(又称natural sorting):

import re 

def atoi(text): 
    return int(text) if text.isdigit() else text 

def natural_keys(text): 
    ''' 
    alist.sort(key=natural_keys) sorts in human order 
    http://nedbatchelder.com/blog/200712/human_sorting.html 
    (See Toothy's implementation in the comments) 
    ''' 
    return [ atoi(c) for c in re.split('(\d+)', text) ] 

alist=[ 
    "something1", 
    "something12", 
    "something17", 
    "something2", 
    "something25", 
    "something29"] 

alist.sort(key=natural_keys) 
print(alist) 

产生

['something1', 'something2', 'something12', 'something17', 'something25', 'something29'] 

PS。我已经改变了我的答案,使用Toothy的自然排序实现(张贴在评论here),因为它比我的原始答案快得多。


如果要排序用浮漂的文本,那么你就需要将正则表达式从一个匹配整数变化(即(\d+))到a regex that matches floats

import re 

def atof(text): 
    try: 
     retval = float(text) 
    except ValueError: 
     retval = text 
    return retval 

def natural_keys(text): 
    ''' 
    alist.sort(key=natural_keys) sorts in human order 
    http://nedbatchelder.com/blog/200712/human_sorting.html 
    (See Toothy's implementation in the comments) 
    float regex comes from https://stackoverflow.com/a/12643073/190597 
    ''' 
    return [ atof(c) for c in re.split(r'[+-]?([0-9]+(?:[.][0-9]*)?|[.][0-9]+)', text) ] 

alist=[ 
    "something1", 
    "something2", 
    "something1.0", 
    "something1.25", 
    "something1.105"] 

alist.sort(key=natural_keys) 
print(alist) 

产生

['something1', 'something1.0', 'something1.105', 'something1.25', 'something2'] 
+0

我可以使用上面的方法对具有子属性(字符串)的对象列表进行排序。用“someobject”替换“text”,然后'在re.split('(\ d +)',someobject.sometextproperty)]'中返回[atoi(c)for c。 – Jonny 2015-08-21 13:48:08

+0

你知道如何将这个扩展到浮点数的情况吗?例如,东西1.0,东西1.25,东西2.0。 – painfulenglish 2017-05-02 10:50:34

+1

@painfulenglish:我修改了上面的帖子,展示了如何使用浮动自然排序文本。 – unutbu 2017-05-02 19:02:38

相关问题