У меня есть набор
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
Любая идея, пожалуйста,
Короткий и сладкий:
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)
Джефф Этвуд рассказывает о естественной сортировке и дает пример одного из способов сделать это в 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).
Простым способом является разбиение строк на числовые части и нечисловые части и использование порядка сортировки кортежей 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)
Вы должны проверить стороннюю библиотеку 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
Было высказано предположение о том, что я перепечатываю этот ответ здесь, так как он отлично подходит для этого случая.
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)]
>>> 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']
Для людей, застрявших с версией Python до 2.4, без замечательной функции sorted()
, быстрый способ сортировки наборов:
l = list(yourSet)
l.sort()
Это не отвечает на конкретный вопрос выше (12 sheets
будет раньше 4 sheets
), но это может быть полезно для людей, прибывающих из Google.
Общий ответ для сортировки любых чисел в любой позиции в массиве строк. Работает с 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']
Часть ответа оттуда