Подтвердить что ты не робот

Как отсортировать буквенно-цифровой набор в python

У меня есть набор

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

После сортировки я хочу, чтобы он выглядел как

4 sheets,
12 sheets,
48 sheets,
booklet

Любая идея, пожалуйста,

4b9b3361

Ответ 1

Короткий и сладкий:

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

Эта версия:

  • Работает в Python 2 и Python 3, потому что:
    • Он не предполагает, что вы сравниваете строки и целые числа (которые не будут работать в Python 3)
    • Он не использует параметр 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)

Ответ 2

Джефф Этвуд рассказывает о естественной сортировке и дает пример одного из способов сделать это в 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).

Ответ 3

Простым способом является разбиение строк на числовые части и нечисловые части и использование порядка сортировки кортежей 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)

Ответ 4

Вы должны проверить стороннюю библиотеку 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

Ответ 5

Было высказано предположение о том, что я перепечатываю этот ответ здесь, так как он отлично подходит для этого случая.

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)]

Ответ 6

>>> 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']

Ответ 7

Множества

по своей сути не упорядочены. Вам нужно будет создать список с тем же содержимым и отсортировать его.

Ответ 8

На основе ответа 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']

Ответ 9

Для людей, застрявших с версией Python до 2.4, без замечательной функции sorted(), быстрый способ сортировки наборов:

l = list(yourSet)
l.sort() 

Это не отвечает на конкретный вопрос выше (12 sheets будет раньше 4 sheets), но это может быть полезно для людей, прибывающих из Google.

Ответ 10

Общий ответ для сортировки любых чисел в любой позиции в массиве строк. Работает с 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']

Часть ответа оттуда