如何sorting在Python中的字母数字集

我有一套

set(['booklet', '4 sheets', '48 sheets', '12 sheets']) 

sorting后,我想它看起来像

 4 sheets, 12 sheets, 48 sheets, booklet 

请任何想法

简短而甜美:

 sorted(data, key=lambda item: (int(item.partition(' ')[0]) if item[0].isdigit() else float('inf'), item)) 

这个版本:

  • 适用于Python 2和Python 3,因为:
    • 它不假设你比较string和整数(这不会在Python 3中工作)
    • 它不使用cmp参数进行sorted (在Python 3中不存在)
  • 如果数量相等,将在string部分sorting

如果您想按照您的示例所述完全打印输出,则:

 data = set(['booklet', '4 sheets', '48 sheets', '12 sheets']) r = sorted(data, key=lambda item: (int(item.partition(' ')[0]) if item[0].isdigit() else float('inf'), item)) print ',\n'.join(r) 

Jeff Atwood谈到了自然sorting,并给出了一个在Python中使用它的方法的例子。 这是我的变化:

 import re def sorted_nicely( l ): """ Sort the given iterable in the way that humans expect.""" convert = lambda text: int(text) if text.isdigit() else text alphanum_key = lambda key: [ convert(c) for c in re.split('([0-9]+)', key) ] return sorted(l, key = alphanum_key) 

像这样使用:

 s = set(['booklet', '4 sheets', '48 sheets', '12 sheets']) for x in sorted_nicely(s): print(x) 

输出:

 4 sheets 12 sheets 48 sheets booklet 

这种方法的一个优点是,当string被空格分隔时,它不会工作。 它也适用于其他分隔符,例如版本号中的期间(例如1.9.1在1.10.0之前)。

一个简单的方法是将string拆分为数字部分和非数字部分,并使用python元组sorting对string进行sorting。

 import re tokenize = re.compile(r'(\d+)|(\D+)').findall def natural_sortkey(string): return tuple(int(num) if num else alpha for num, alpha in tokenize(string)) sorted(my_set, key=natural_sortkey) 

你应该检查出第三方库natsort 。 它的algorithm是一般的,所以它可以用于大多数input。

 >>> import natsort >>> your_list = set(['booklet', '4 sheets', '48 sheets', '12 sheets']) >>> print ',\n'.join(natsort.natsorted(your_list)) 4 sheets, 12 sheets, 48 sheets, booklet 

有人build议我在这里重新发布这个答案 ,因为它也适用于这种情况

 from itertools import groupby def keyfunc(s): return [int(''.join(g)) if k else ''.join(g) for k, g in groupby(s, str.isdigit)] sorted(my_list, key=keyfunc) 

演示:

 >>> my_set = {'booklet', '4 sheets', '48 sheets', '12 sheets'} >>> sorted(my_set, key=keyfunc) ['4 sheets', '12 sheets', '48 sheets', 'booklet'] 

对于Python3,有必要稍微修改一下(这个版本在Python2中也能正常工作)

 def keyfunc(s): return [int(''.join(g)) if k else ''.join(g) for k, g in groupby('\0'+s, str.isdigit)] 

集合本质上是无序的。 您需要创build一个具有相同内容的列表并对其进行sorting。

 >>> a = set(['booklet', '4 sheets', '48 sheets', '12 sheets']) >>> def ke(s): i, sp, _ = s.partition(' ') if i.isnumeric(): return int(i) return float('inf') >>> sorted(a, key=ke) ['4 sheets', '12 sheets', '48 sheets', 'booklet'] 

根据SilentGhost的回答:

 In [4]: a = set(['booklet', '4 sheets', '48 sheets', '12 sheets']) In [5]: def f(x): ...: num = x.split(None, 1)[0] ...: if num.isdigit(): ...: return int(num) ...: return x ...: In [6]: sorted(a, key=f) Out[6]: ['4 sheets', '12 sheets', '48 sheets', 'booklet'] 

对于那些坚持2.4以前版本的Python的人来说,如果没有美妙的sorted()函数,快速的sorting方法是:

 l = list(yourSet) l.sort() 

这并没有回答上面的具体问题( 12 sheets将在4 sheets之前),但它可能对来自Google的人有用。

通用答案,sortingstring数组中任何位置的任何数字。 适用于Python 2&3。

 def alphaNumOrder(string): """ Returns all numbers on 5 digits to let sort the string with numeric order. Ex: alphaNumOrder("a6b12.125") ==> "a00006b00012.00125" """ return ''.join([format(int(x), '05d') if x.isdigit() else x for x in re.split(r'(\d+)', string)]) 

样品:

 s = ['a10b20','a10b1','a3','b1b1','a06b03','a6b2','a6b2c10','a6b2c5'] s.sort(key=alphaNumOrder) s ===> ['a3', 'a6b2', 'a6b2c5', 'a6b2c10', 'a06b03', 'a10b1', 'a10b20', 'b1b1'] 

部分答案是从那里