Как отсортировать список строк по цифрам?

128

Я знаю, что это звучит банально, но я не осознавал, что sort()функция Python была странной. У меня есть список «чисел», которые на самом деле представлены в строковой форме, поэтому я сначала конвертирую их в целые числа, а затем пытаюсь выполнить сортировку.

list1=["1","10","3","22","23","4","2","200"]
for item in list1:
    item=int(item)

list1.sort()
print list1

Дает мне:

['1', '10', '2', '200', '22', '23', '3', '4']

Я хочу

['1','2','3','4','10','22','23','200']

Я поискал некоторые алгоритмы, связанные с сортировкой числовых наборов, но все те, которые я нашел, включают сортировку буквенно-цифровых наборов.

Я знаю, что это, вероятно, простая проблема, но Google и мой учебник не предлагают ничего более или менее полезного, чем эта .sort()функция.

Брайан
источник
9
Обратите внимание, что ваш цикл for не выполняет то, что я подозреваю, как вы думаете.
deinst
1
Ни разу не обновлял list1. Что заставило вас подумать, listчто идет обновление?
S.Lott
Аналогичная проблема возникает, когда list1 = ['1', '1.10', '1.11', '1.1', '1.2'] предоставляется в качестве входных данных. Вместо вывода в виде ['1', '1.1', '1.2', '1.10', '1.11'] я получаю ['1', '1.1', '1.10', '1.11', '1.2' ]
sathish
2
в python 3 вы можете захотеть использоватьsorted(mylist)
Акин Хван

Ответы:

191

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

list1 = ["1","10","3","22","23","4","2","200"]
list1 = [int(x) for x in list1]
list1.sort()

Если по какой-то причине вам нужно сохранить строки вместо целых чисел (обычно это плохая идея, но, возможно, вам нужно сохранить ведущие нули или что-то еще), вы можете использовать ключевую функцию. sortпринимает именованный параметр, keyкоторый является функцией, вызываемой для каждого элемента перед его сравнением. Вместо прямого сравнения элементов списка сравниваются возвращаемые значения ключевой функции:

list1 = ["1","10","3","22","23","4","2","200"]
# call int(x) on each element before comparing it
list1.sort(key=int)
Симус Кэмпбелл
источник
8
когда я пробую key = int в 2.7, я получаю None
KI4JGT
1
Это работает, если элемент списка хранится как "целое число", как следует обрабатывать значения с плавающей запятой? Например, list1 = [1, 1.10, 1.11, 1.1, 1.2]
sathish
1
@ KI4JGT метод сортировки изменяет список и возвращает None. Так что вместо list1 = list1.sort(key=int), используйте только list1.sort(key=int)и list1 уже будет отсортирован.
Josiah Yoder
1
@ KI4JGT .sort () - это оператор на месте, он возвращает None, он сортирует список, вы можете использовать
sorted
39

Вы можете передать функцию в keyпараметра в .sortметоде . При этом система будет отсортировать по ключу (x) вместо x.

list1.sort(key=int)

Кстати, для преобразования списка в целые числа постоянно, использовать в mapфункцию

list1 = list(map(int, list1))   # you don't need to call list() in Python 2.x

или понимание списка

list1 = [int(x) for x in list1]
kennytm
источник
21

Если вы хотите использовать sorted()функцию:sorted(list1, key=int)

Он возвращает новый отсортированный список.

сям
источник
1
Работает и с наборами!
MT
12

Сортировка в Python не такая уж странная. Просто этот код:

for item in list1:
   item=int(item)

не делает то, что вы думаете - itemне заменяется обратно в список, а просто выбрасывается.

В любом случае, правильное решение - использовать то, key=intчто вам показали другие.

Дэниел Розман
источник
12

Вы также можете использовать:

import re

def sort_human(l):
    convert = lambda text: float(text) if text.isdigit() else text
    alphanum = lambda key: [convert(c) for c in re.split('([-+]?[0-9]*\.?[0-9]*)', key)]
    l.sort(key=alphanum)
    return l

Это очень похоже на другие вещи, которые вы можете найти в Интернете, но также работает для буквенно-цифровых символов, таких как [abc0.1, abc0.2, ...].

юлианский
источник
9

Вчера я подошел к той же проблеме и нашел модуль под названием [natsort] [1], который решает вашу проблему. Использование:

from natsort import natsorted # pip install natsort

# Example list of strings
a = ['1', '10', '2', '3', '11']

[In]  sorted(a)
[Out] ['1', '10', '11', '2', '3']

[In]  natsorted(a)
[Out] ['1', '2', '3', '10', '11']

# Your array may contain strings
[In]  natsorted(['string11', 'string3', 'string1', 'string10', 'string100'])
[Out] ['string1', 'string3', 'string10', 'string11', 'string100']

Он также работает со словарями как эквивалент sorted. [1]: https://pypi.org/project/natsort/

rfaenger
источник
8

Ответ Симуса Кэмпбелла не работает на python2.x.
list1 = sorted(list1, key=lambda e: int(e))использование lambdaфункции работает хорошо.

Маркс Вольф
источник
3

Попробуйте это, он отсортирует список на месте в порядке убывания (в этом случае нет необходимости указывать ключ):

Обработать

listB = [24, 13, -15, -36, 8, 22, 48, 25, 46, -9]
listC = sorted(listB, reverse=True) # listB remains untouched
print listC

вывод:

 [48, 46, 25, 24, 22, 13, 8, -9, -15, -36]
Мавия
источник
0

Самое последнее решение верное. Вы читаете решения в виде строки, и в этом случае порядок равен 1, затем 100, затем 104, затем 2, затем 21, затем 2001001010, 3 и так далее.

Вместо этого вы должны передать свой ввод как int:

отсортированные строки:

stringList = (1, 10, 2, 21, 3)

отсортированные целые числа:

intList = (1, 2, 3, 10, 21)

Для преобразования просто поместите stringList в int (blahblah).

Очередной раз:

stringList = (1, 10, 2, 21, 3)

newList = int (stringList)

print newList

=> returns (1, 2, 3, 10, 21) 
Клинт
источник
1
TypeError: аргумент int () должен быть строкой или числом, а не кортежем,
Сейс Тиммерман
Кроме того, строки в вашем списке строк должны иметь кавычки.
Teepeemm
2
Это ужасный прогноз: «самое последнее решение верное»;)
GreenAsJade
0

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

list1=["1","10","3","22","23","4","2","200"]

k=[]    
for item in list1:    
    k.append(int(item))

k.sort()
print(k)
# [1, 2, 3, 4, 10, 22, 23, 200]
Shaystorm
источник
0

Простой способ отсортировать числовой список

numlists = ["5","50","7","51","87","97","53"]
results = list(map(int, numlists))
results.sort(reverse=False)
print(results)
sayalok
источник
-1

настоящая проблема в том, что сортировка сортирует вещи по алфавиту. Итак, если у вас есть список ['1', '2', '10', '19'] и вы запустите sort, вы получите ['1', '10'. «19», «2»]. т.е. 10 идет до 2, потому что он смотрит на первый символ и сортирует, начиная с него. Кажется, что большинство методов в python возвращают вещи именно в таком порядке. Например, если у вас есть каталог с именем abc с файлами, помеченными как 1.jpg, 2.jpg и т. Д., Скажем, до 15.jpg, и вы выполняете file_list = os.listdir (abc), file_list упорядочен не так, как вы ожидаете, а как file_list = ['1.jpg', '11 .jpg '---' 15.jpg ',' 2.jpg]. Если порядок, в котором обрабатываются файлы, важен (вероятно, поэтому вы назвали их численно), он не такой, как вы думаете. Вы можете избежать этого, используя заполнение "нулями". Например, если у вас есть список alist = ['01', '03', '05', '10', '02', '04', '06] и вы запускаете по нему сортировку, вы получаете желаемый порядок. alist = ['01', '02' и т. д.], потому что первый символ - это 0, который стоит перед 1. Количество нулей, которые вам нужно заполнить, определяется наибольшим значением в списке. Например, если наибольшее значение находится в диапазоне от 100 до 1000 вам нужно заполнить однозначными числами 001, 002 --- 010011-100, 101 и т. Д.

Джерри П.
источник
-5
scores = ['91','89','87','86','85']
scores.sort()
print (scores)

Это сработало для меня с использованием Python версии 3, но не с версией 2.

Камаль Редди
источник
3
Попробуйте отсортировать там «11» и «100», тогда все станет интересно.
Penz