Python сортирует строки с цифрами в конце - PullRequest
7 голосов
/ 30 ноября 2010

Какой самый простой способ отсортировать список строк с цифрами в конце, где у некоторых есть 3 цифры, а у некоторых 4:

>>> list = ['asdf123', 'asdf1234', 'asdf111', 'asdf124']
>>> list.sort()
>>> print list
['asdf111', 'asdf123', 'asdf1234', 'asdf124']

следует поставить одну 1234 на конце.Есть ли простой способ сделать это?

Ответы [ 8 ]

12 голосов
/ 15 января 2015

Есть ли простой способ сделать это?

Да

Вы можете использовать модуль natsort .

>>> from natsort import natsorted
>>> natsorted(['asdf123', 'asdf1234', 'asdf111', 'asdf124'])
['asdf111', 'asdf123', 'asdf124', 'asdf1234']

Полное раскрытие, я автор пакета.

5 голосов
/ 30 ноября 2010

Есть ли простой способ сделать это?

нет

Нет

Совершенно неясно, каковы настоящие правила. «У некоторых есть 3 цифры, а у некоторых 4», на самом деле не очень точная или полная спецификация. Все ваши примеры показывают 4 буквы перед цифрами. Это всегда так?

import re
key_pat = re.compile(r"^(\D+)(\d+)$")
def key(item):
    m = key_pat.match(item)
    return m.group(1), int(m.group(2))

Эта key функция может делать то, что вы хотите. Или это может быть слишком сложно. Или, может быть, модель действительно r"^(.*)(\d{3,4})$" или, может быть, правила еще более неясны.

>>> data= ['asdf123', 'asdf1234', 'asdf111', 'asdf124']
>>> data.sort( key=key )
>>> data
['asdf111', 'asdf123', 'asdf124', 'asdf1234']
1 голос
/ 01 декабря 2010

То, что вы, вероятно, описываете, называется Естественная сортировка , или Человеческая сортировка.Если вы используете Python, вы можете позаимствовать у реализацию Неда .

Алгоритм естественной сортировки примерно таков:

  • Разделить каждое значение наалфавитные "чанки" и числовые "чанки"
  • Сортировка по первому чанку каждого значения
    • Если чанк алфавитный, сортируйте его как обычно
    • Если чанк числовойСортировка по числовому значению
  • Возьмите значения, имеющие один и тот же первый блок, и отсортируйте их по второму фрагменту
  • И так далее
1 голос
/ 30 ноября 2010

Вам нужна ключевая функция. Вы готовы указать 3 или 4 цифры в конце, и я чувствую, что вы хотите, чтобы они сравнивались численно.

sorted(list_, key=lambda s: (s[:-4], int(s[-4:])) if s[-4] in '0123456789' else (s[:-3], int(s[-3:]))) 

Без лямбды и условного выражения, это

def key(s):
    if key[-4] in '0123456789':
         return (s[:-4], int(s[-4:]))
    else:
         return (s[:-3], int(s[-3:]))

sorted(list_, key=key)

Это просто использует тот факт, что кортежи сортируются по первому элементу, а затем по второму. Так как функция key вызывается для получения значения для сравнения, элементы теперь будут сравниваться как кортежи, возвращаемые функцией key. Например, 'asdfbad123' будет сравниваться с 'asd7890', тогда как ('asdfbad', 123) сравнивается с ('asd', 7890). Если последние 3 символа строки на самом деле не являются цифрами, вы получите ValueError, который совершенно уместен, учитывая тот факт, что вы передали ему данные, которые не соответствуют спецификациям, для которых он был разработан.

1 голос
/ 30 ноября 2010
l = ['asdf123', 'asdf1234', 'asdf111', 'asdf124']
l.sort(cmp=lambda x,y:cmp(int(x[4:]), int(y[4:]))
1 голос
/ 30 ноября 2010

Проблема в том, что сортировка здесь в алфавитном порядке, поскольку они являются строками .Каждая последовательность символов сравнивается перед переходом к следующему символу.

>>> 'a1234' < 'a124'  <----- positionally '3' is less than '4' 
True
>>> 

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

>>> x = ['asdf123', 'asdf1234', 'asdf111', 'asdf124']
>>> y = [ int(t[4:]) for t in x]
>>> z = sorted(y)
>>> z
[111, 123, 124, 1234]
>>> l = ['asdf'+str(t) for t in z]
>>> l
['asdf111', 'asdf123', 'asdf124', 'asdf1234']
>>> 
0 голосов
/ 13 октября 2016

вместо того, чтобы разбивать каждую строку самостоятельно, я прошу python сделать это для меня с помощью re.findall():

import re
import sys

def SortKey(line):
  result = []
  for part in re.findall(r'\D+|\d+', line):
    try:
      result.append(int(part, 10))
    except (TypeError, ValueError) as _:
      result.append(part)
  return result

print ''.join(sorted(sys.stdin.readlines(), key=SortKey)),
0 голосов
/ 30 ноября 2010
L.sort(key=lambda s:int(''.join(filter(str.isdigit,s[-4:]))))
...