#python #list #sorting
#python #Список #сортировка
Вопрос:
list1 = ["1.11", "2.0.0", "1.2", "2", "0.1", "1.2.1", "1.1.1", "2.0"]
from operator import itemgetter
def solution(data):
parse_list = []
parse_list2 = []
final_solution = []
for x in data:
y = x.split('.')
if len(y) == 1:
x = "{}.{}.{}".format(y[0], '-1', '-1')
parse_list.append(x)
if len(y) == 2:
x = "{}.{}.{}".format(y[0], y[1], '-1')
parse_list.append(x)
if len(y) == 3:
x = "{}.{}.{}".format(y[0], y[1], y[2])
parse_list.append(x)
print(parse_list)
parse_list2 = sorted(parse_list, key=itemgetter(0, 1, 2))
# print(parse_list)
print(parse_list2)
def unparse(x):
y = x.split('.')
if int(y[1]) < 0:
x = '{}'.format(y[0])
final_solution.append(x)
return
if int(y[2]) == -1:
x = '{}.{}'.format(y[0], y[1],)
final_solution.append(x)
return
if int(y[2]) >= 0:
x = '{}.{}.{}'.format(y[0], y[1], y[2])
final_solution.append(x)
return
for x in parse_list2:
x = unparse(x)
print(final_solution)
вывод:
['1.11.-1', '2.0.0', '1.2.-1', '2.-1.-1', '0.1.-1', '1.2.1', '1.1.1', '2.0.-1']
['0.1.-1', '1.11.-1', '1.1.1', '1.2.-1', '1.2.1', '2.-1.-1', '2.0.0', '2.0.-1']
['0.1', '1.11', '1.1.1', '1.2', '1.2.1', '2', '2.0.0', '2.0']
Я не понимаю, почему
parse_list2 = sorted(parse_list, key=itemgetter(0, 1, 2))
не сортирует вывод в
['1.11.-1', '2.0.0', '1.2.-1', '2.-1.-1', '0.1.-1', '1.2.1', '1.1.1', '2.0.-1']
['0.1.-1', '1.1.1', '1.2.-1', '1.2.1', '1.11.-1', '2.-1.-1', '2.0.0', '2.0.-1']
['0.1', '1.1.1', '1.2', '1.2.1', '1.11', '2', '2.0.0', '2.0']
потому что 2 меньше 11
Пожалуйста, кто-нибудь может помочь мне настроить мой код для работы (в отличие от предоставления мне другого, но функционального кода) или объяснить мне, почему моя логика не будет работать.
Комментарии:
1.
"11" < "2"
этоTrue
потому"1" < "2"
, что. Если вы хотите сравнить цифры, вам нужно либо преобразовать их в целые числа, либо в числа с плавающей точкой, чтобы они правильно сортировались.2. Добро пожаловать в SO! Строки упорядочены лексикографически. Разберите их на целые числа. Цель здесь просто отсортировать эти строки версии, которые имеют отрицательные числа? В чем описание проблемы? Конечно, есть лучший способ решить эту проблему, что бы это ни было…
3. Все, что вы делаете, это сортировка по первым 3 символам каждой строки. Он не пытается интерпретировать многозначные поля. Итак, для
'1.11.-1'
он использует('1', '.', '1')
в качестве ключа сортировки.4. Может кто-нибудь дать мне указатель на превращение их в целые числа? Я пытался, но столкнулся с проблемой, что мне не нравится, когда я пытаюсь изменить список на тип integer.
5.
itemgetter(0, 1, 2)
получает первый, второй и третий символ в строке, а не числа. Почему бы вам не сохранить их как кортежи целых(int(y[0]), int(y[1]), int(y[2]))
и просто отсортировать их (не требуется специального ключевого аргумента)?
Ответ №1:
Ваши значения не отсортированы, потому что они сравнивают строки, а не целые числа.
Вот как я бы отсортировал их вместо этого:
def toIntList(x):
intList = []
for value in x.split("."):
intList.append(int(value))
return intList
list1 = ["1.11", "2.0.0", "1.2", "2", "0.1", "1.2.1", "1.1.1", "2.0"]
# Using a function
sort1 = sorted(list1, key=toIntList)
# Using a lambda-function:
sort2 = sorted(list1, key=lambda x: [int(i) for i in x.split(".")])
print(list1) # Output: ['1.11', '2.0.0', '1.2', '2', '0.1', '1.2.1', '1.1.1', '2.0']
print(sort1) # Output: ['0.1', '1.1.1', '1.2', '1.2.1', '1.11', '2', '2.0', '2.0.0']
print(sort2) # Output: ['0.1', '1.1.1', '1.2', '1.2.1', '1.11', '2', '2.0', '2.0.0']
Комментарии:
1. Хороший подход! Автор попросил не предоставлять другое решение.
Ответ №2:
Несколько советов:
import
всегда в начале (я удалил его, потому что я его больше не использую, но всегда сохраняю их в верхней части файла, обычно три блока импорта: сначала стандартные библиотеки, затем сторонние библиотеки и третий импорт в другие файлы вашей программы)- 2 пустые строки между объявлениями функции первого уровня и класса
elif
не будет пытаться выполнить условие, если предыдущее было истинным, поэтому мы избегаем ненужной проверки условий.parse_list
собирается хранить кортежи из трех целых чисел, такие как(1, 11, -1)
.parse_list = sorted(parse_list)
эквивалентноparse_list.sort()
который делает это на месте.unparse
Функция будет возвращать каждое значение вместо добавления вfinal_solution
список, который принадлежитsolution
функции, а неunparse
функции.
def solution(data):
parse_list = []
for x in data:
y = x.split('.')
if len(y) == 1:
parse_list.append((int(y[0]), -1, -1))
elif len(y) == 2:
parse_list.append((int(y[0]), int(y[1]), -1))
elif len(y) == 3:
parse_list.append((int(y[0]), int(y[1]), int(y[2])))
print(parse_list)
parse_list.sort()
print(parse_list)
def unparse(x):
if x[1] < 0:
return '{}'.format(x[0])
if x[2] < 0:
return '{}.{}'.format(x[0], x[1])
return '{}.{}.{}'.format(x[0], x[1], x[2])
final_solution = []
for x in parse_list:
final_solution.append(unparse(x))
print(final_solution)
if __name__ == '__main__':
list1 = ["1.11", "2.0.0", "1.2", "2", "0.1", "1.2.1", "1.1.1", "2.0"]
solution(list1)
Это также может быть оптимизировано:
def solution(data):
parse_list = sorted([tuple(map(int, item.split('.'))) for item in data])
final_solution = ['.'.join(map(str, item)) for item in parse_list]
print(final_solution)
if __name__ == '__main__':
list1 = ["1.11", "2.0.0", "1.2", "2", "0.1", "1.2.1", "1.1.1", "2.0"]
solution(list1)
Давайте разберем это решение:
[doSomethingWith(item) for item in data]
создает список, в котором каждый элемент является тем, чтоdoSomethingWith(item)
есть, используя каждый раз один из элементовdata
.doSomethingWith(item)
в нашем случаеtuple(map(int, item.split('.')))
:item
например"1.11"
item.split('.')
выдает нам список строк:["1", "11"]
map(f, iterable)
применяет функциюf
к каждому элементу iterable и возвращает объект, подобный списку (это не совсем список, но похожий). В нашем случаеf
этоint
так, что мы преобразуем подстроки в целые числа:[1, 11]
<- На самом деле не список, но похожий- Мы преобразуем этот объект, подобный списку, в кортеж с внешним
tuple()
:(1, 11)
- Внешний
sorted()
будет сортировать этот список, не нужно беспокоиться о недостающих элементах, так как(1, 0) < (1, 0, 0)
они будут отсортированы должным образом. - Итак,
parse_list
это уже отсортированный список кортежей целых чисел:[(0, 1), (1, 1, 1), ...]
- Снова
[doSomethingWith(item) for item in parse_list]
оператор, поэтому мы создаем новый список, что-то делая с каждым элементом вparse_list
. doSomethingWith(item)
в этом случае'.'.join(map(str, item))
:item
например(1, 11)
map(str, item)
преобразует каждый элемент, который уitem
нас есть, в строки:["1", "11"]
<- На самом деле не список, но похожий'.'.join()
объединяет список строк с помощью ‘.’:"1.11"
- Итак,
final_result
это желаемый результат:["0.1", "1.1.1", ...]