Как отсортировать список номеров разделов в Python? [Дубликат]

На этот вопрос уже есть ответ здесь:

Сортировка списка разделенных точками чисел, например, версий программного обеспечения 4 ответа

Разделы книги обычно нумеруются какx.x.x, такие как1.2.3. Как отсортировать список номеров разделов?

Сохраните номера разделов в виде списка строк.

# a list of strings, section numbers
ls = ['1.1', '1.10', '1.2', '1.2.3', '1.2.1', '1.9']    

lists = sorted([s.split('.') for s in ls], key=lambda x:map(int, x))    
# [['1', '1'], ['1', '2'], ['1', '2', '1'], ['1', '2', '3'], ['1', '9'], ['1', '10']]

r = ['.'.join(sublist) for sublist in lists]    
#['1.1', '1.2', '1.2.1', '1.2.3', '1.9', '1.10']

Тем не менее, мой ожидаемый результат,

['1.1', '1.10', '1.2', '1.2.1', '1.2.3', '1.9']
 Kevin02 июн. 2016 г., 17:17
поплавки уже не рекомендуется, но вот еще один гвоздь в гробу: как вы собираетесь представлять главу 1, раздел 2, подраздел 3?
 Two-Bit Alchemist02 июн. 2016 г., 17:19
@ Sparkandshine Это не сработает. Это ошибка синтаксиса!
 Vincent Savard02 июн. 2016 г., 17:12
1.10 это не номер раздела, это число с плавающей точкой. Если вам нужен объект, представляющий номер раздела, создайте для него класс. Использование поплавка для этого - ужасная идея.
 Colonel Beauvel02 июн. 2016 г., 17:18
ты уверен, что не говоришь о строке в lf?
 SparkAndShine02 июн. 2016 г., 17:16
@ VincentSavard, я вижу.1.10 представляет главу1, Раздел10.
 SparkAndShine02 июн. 2016 г., 17:18
@Kevin,1.2.3, Мне нужно отредактировать мой вопрос.
 Vincent Savard02 июн. 2016 г., 17:18
@sparkandshineI знаю, что ты имел в виду,питон не. Вот почему типы важны. Ваше намерение может быть прояснено с помощью фактического класса, который кодирует номер раздела.
 dhke02 июн. 2016 г., 17:13
Неверный тип данных ввода. Номера секций не являются числами с плавающей точкой, они больше похожи на полиномиальные коэффициенты, которые сортируются лексикографически. При использовании поплавков,1.1 семантически равен1.10, но это не то, что вы хотите. Сохраняйте значения в виде строк и сортируйте по разбиению. Или даже лучше: создайте правильный тип.
 Two-Bit Alchemist02 июн. 2016 г., 17:17
Почему бы не хранить их как строки в первую очередь? Использование поплавков для этого вызывает всю эту проблему.1.10 == 1.1 и вы не можете сделать это неправдой, пока вы используете цифры. Это не числовые данные.

Ответы на вопрос(3)

Решение Вопроса

которая преобразует строки в подсписки целых чисел. Те будут сортировать правильно без проблем.

In [4]: ls = ['1.1', '1.10', '1.2', '1.2.3', '1.2.1', '1.9']

In [5]: def section(s):
   ...:     return [int(_) for _ in s.split(".")]
   ...:

In [6]: sorted(ls, key=section)
Out[6]: ['1.1', '1.2', '1.2.1', '1.2.3', '1.9', '1.10']
 Tim Pietzcker02 июн. 2016 г., 17:31
@julivico: Конечно, это по сути то же самое.
 Jstuff02 июн. 2016 г., 17:57
@TimPietzcker есть способ использовать эту функцию с функцией zip. Я знаю, что это неправильно, но это выглядело бы так: )
 Tim Pietzcker02 июн. 2016 г., 18:20
@Jstuff: Итак, вы хотите объединить четыре списка и отсортировать их в том же порядке, что иl1? А для чего нужен второй ключ?
 qvpham02 июн. 2016 г., 17:30
Могу ли я использоватьlambda лайкsorted(ls, key=lambda x: [int(_) for _ in x.split('.')])?
 Jstuff02 июн. 2016 г., 18:25
Да, но l1 - это список строк с плавающими значениями. Если я просто сделаю result = list (zip (* sorted (zip (l1, l2, l3, files_good_list), key = lambda x: float (x [0])))). Он будет сортировать l1 как 1.1, 1.10, 1.2, а не 1.1, 1.2, 1.10. Поэтому мне нужен второй ключ, чтобы отсортировать его, как вы сделали в ответе на вопрос. Вопрос, на который вы ответили, возник из-за этого поста (stackoverflow.com/questions/37592787/...Возможно, это прояснит ситуацию.

float это не тот тип данных, который вам нужен. В вашем случае у вас есть фактическая иерархия глав / разделов.

Один простой (и помните, простой лучше, чем сложный) способ - представлять номера разделов в виде кортежей. Поскольку кортежи отсортированы лексикографически, они, естественно, сортируются в нужном порядке:

>>> lf = [(1, ), (1, 1), (1, 10), (1, 3), (1, 4), (1, 5), (1, 6), (1, 7), (1, 8), (2, ), (1, 9)]
>>> sorted(lf)
[(1, ), (1, 1), (1, 3), (1, 4), (1, 5), (1, 6), (1, 7), (1, 8), (1, 9), (1, 10), (2, )]

Как мы видим, это также работает для кортежей различной длины.

Если вы хотите сохранить разделы в виде строк,natsort отлично справляется и с точечными значениями:

>>> s = ['1', '1.1', '1.10', '1.2']
>>> natsort.natsorted(s)
['1', '1.1', '1.2', '1.10']

Вы также можете определить свой собственныйSectionNumber класс, но это, вероятно, излишне.

Почему бы не хранить номера разделов в виде кортежей?

sections = [(2, 4, 1), (1, 10, 3),(1, 2, 1), (1, 1, 10), (1, 2, 3), (1, 4, 6)]

print(sorted(sections)) 

дает[(1, 1, 10), (1, 2, 1), (1, 2, 3), (1, 4, 6), (1, 10, 3), (2, 4, 1)]

 dhke02 июн. 2016 г., 17:31
@ Sparkandshine ... даже тогда вы получите правильную сортировку.(2, 1) сортирует перед(2, 1, 3)который сортирует раньше(2, 2).
 SparkAndShine02 июн. 2016 г., 17:29
Размер кортежей может быть разным, например,2.1 а также2.1.3.

Ваш ответ на вопрос