Могу ли я отсортировать текст по его числовому значению в Python?

У меня есть dict в Python с ключами следующей формы:

mydict = {'0'     : 10,
          '1'     : 23,
          '2.0'   : 321,
          '2.1'   : 3231,
          '3'     : 3,
          '4.0.0' : 1,
          '4.0.1' : 10,
          '5'     : 11,
          # ... etc
          '10'    : 32,
          '11.0'  : 3,
          '11.1'  : 243,
          '12.0'  : 3,
          '12.1.0': 1,
          '12.1.1': 2,
          }

Некоторые индексы не имеют подначислений, некоторые из них имеют один уровень суб-значений, а у некоторых - два. Если бы у меня был только один подъярус, я мог бы рассматривать их все как числа и сортировать численно. Второй под-уровень заставляет меня обрабатывать их все как строки. Однако, если я отсортирую их как строки, у меня будет 10 после 1 и 20 следующих 2.

Как я могу правильно отсортировать индексы?

Примечание.. Я действительно хочу распечатать dict, отсортированный по индексу. Если есть лучший способ сделать это, чем сортировать его как-то так хорошо со мной.

Ответ 1

Вы можете сортировать ключи так, как хотите, разделив их на. и затем преобразование каждого из компонентов в целое число, например:

sorted(mydict.keys(), key=lambda a:map(int,a.split('.')))

который возвращает это:

['0',
 '1',
 '2.0',
 '2.1',
 '3',
 '4.0.0',
 '4.0.1',
 '5',
 '10',
 '11.0',
 '11.1',
 '12.0',
 '12.1.0',
 '12.1.1']

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

Вы также можете отсортировать результат mydict.items(), очень похожим:

sorted(mydict.items(), key=lambda a:map(int,a[0].split('.')))

Это дает вам отсортированный список пар (ключ, значение), например:

[('0', 10),
 ('1', 23),
 ('2.0', 321),
 ('2.1', 3231),
 ('3', 3),
 # ...
 ('12.1.1', 2)]

Ответ 2

Функции сортировки Python могут выполнять пользовательскую функцию сравнения, поэтому вам просто нужно определить функцию, которая сравнивает ключи так, как вам нравится:

def version_cmp(a, b):
  '''These keys just look like version numbers to me....'''
  ai = map(int, a.split('.'))
  bi = map(int, b.split('.'))
  return cmp(ai, bi)

for k in sorted(mydict.keys(), version_cmp):
  print k, mydict[k]

В этом случае вам лучше использовать параметр key для sorted(). См. Ian Clelland для примера.

Ответ 3

В качестве дополнения к

Ответ 4

Для удовольствия и полезности (в основном для googling ppl):

f = lambda i: [int(j) if re.match(r"[0-9]+", j) else j for j in re.findall(r"([0-9]+|[^0-9]+)", i)]
cmpg = lambda x, y: cmp(f(x), f(y))

используйте sorted(list, cmp=cmpg). Кроме того, регулярные выражения могут быть предварительно скомпилированы (редко необходимы, хотя, фактически, с повторным кэшированием модулей). И, может быть (легко) изменено, например, включить отрицательные значения (добавьте -? в num regex, возможно) и/или использовать значения float.

Это может быть не очень эффективно, но даже при этом это очень полезно.

И, uhm, его можно использовать как key = для sorted() тоже.

Ответ 6

На веб-сайте python есть хорошая сортировка HOWTO: http://wiki.python.org/moin/HowTo/Sorting. Он дает хорошее представление о сортировке и обсуждает различные методы адаптации результата сортировки к вашим потребностям.