【发布时间】:2023-03-06 15:29:01
【问题描述】:
我有一套
set(['booklet', '4 sheets', '48 sheets', '12 sheets'])
排序后我希望它看起来像
4 sheets,
12 sheets,
48 sheets,
booklet
有什么建议
【问题讨论】:
我有一套
set(['booklet', '4 sheets', '48 sheets', '12 sheets'])
排序后我希望它看起来像
4 sheets,
12 sheets,
48 sheets,
booklet
有什么建议
【问题讨论】:
Jeff Atwood 谈到了自然排序,并举例说明了在 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
这种方法的一个优点是它不仅仅在字符串用空格分隔时起作用。它也适用于其他分隔符,例如版本号中的句点(例如 1.9.1 在 1.10.0 之前)。
【讨论】:
[('b', 0), ('0', 1), ('a', 2)] 排序为[('0', 1), ('a', 2), ('b', 0)]
re.split 中将 .lower() 添加到 key。
key 之后在alphanum_key lambda 函数中添加[0]:lambda key: [ convert(c) for c in re.split('([0-9]+)', key[0]) ]
又短又甜:
sorted(data, key=lambda item: (int(item.partition(' ')[0])
if item[0].isdigit() else float('inf'), item))
这个版本:
cmp 参数到sorted(Python 3 中不存在)如果您想要完全按照示例中描述的方式打印输出,那么:
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)
【讨论】:
4a sheets 感到窒息,但谁在乎呢?要解决这个问题,您需要一个真正的函数而不是 lambda。
您应该查看第三方库natsort。它的算法是通用的,因此它适用于大多数输入。
>>> 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
【讨论】:
一种简单的方法是将字符串拆分为数字部分和非数字部分,并使用 python 元组排序顺序对字符串进行排序。
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)
【讨论】:
建议我在这里重新发布this answer,因为它也适用于这种情况
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)]
【讨论】:
对字符串数组中任意位置的任意数字进行排序的通用答案。适用于 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']
部分答案is from there
【讨论】:
>>> 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() 函数的人来说,对集合进行排序的快速方法是:
l = list(yourSet)
l.sort()
这并不能回答上面的具体问题(12 sheets 将在 4 sheets 之前出现),但它可能对来自 Google 的人有用。
【讨论】:
b = set(['booklet', '10-b40', 'z94 boots', '4 sheets', '48 sheets',
'12 sheets', '1 thing', '4a sheets', '4b sheets', '2temptations'])
numList = sorted([x for x in b if x.split(' ')[0].isdigit()],
key=lambda x: int(x.split(' ')[0]))
alphaList = sorted([x for x in b if not x.split(' ')[0].isdigit()])
sortedList = numList + alphaList
print(sortedList)
Out: ['1 thing',
'4 sheets',
'12 sheets',
'48 sheets',
'10-b40',
'2temptations',
'4a sheets',
'4b sheets',
'booklet',
'z94 boots']
【讨论】: