2011-05-11 27 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

相關問題