如何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']
部分答案是从那里