Як сортувати список рядків чисельно?


128

Я знаю, що це звучить тривіально, але я не розумів, що sort()функція Python була дивною. У мене є список "чисел", які насправді є строковою формою, тому я спершу перетворюю їх у ints, а потім намагаюся сортувати.

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 не робить те, що я підозрюю, що ви вважаєте, що це робить.
деінст

1
Ніколи ви не оновлювали list1. Що ви змусили вас думати, listщо оновлюється?
С.Лотт

Аналогічна проблема виникає, коли список1 = ['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' ]
сатиш

2
в python 3, який ви можете використатиsorted(mylist)
Акін Хван

Відповіді:


191

Ви фактично не перетворили свої рядки в ints. А точніше, ви зробили, але тоді ви нічого не зробили з результатами. Що ви хочете, це:

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

Якщо з якоїсь причини вам потрібно зберегти рядки замість ints (зазвичай це погана ідея, але, можливо, вам потрібно зберегти провідні нулі чи щось таке), ви можете скористатися функцією клавіш . 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
Це працює, якщо елемент списку зберігається як "ціле число", як поводитися з ним у випадку значень float? Напр., List1 = [1, 1.10, 1.11, 1.1, 1.2]
сатиш

1
@ KI4JGT метод сортування змінює список і повертає None. Тож замість list1 = list1.sort(key=int), просто використовувати list1.sort(key=int)і список1 вже буде відсортовано.
Йосія Йодер

1
@ KI4JGT .sort () - це оператор на місці, він повертає None, він сортує список, ви можете використовувати sorted ()
sherpya

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]

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/


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 () повинен бути рядок або число, а не "кортеж"
Cees Timmerman

Також рядки у stringList повинні мати лапки.
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]

0

Простий спосіб сортування числового списку

numlists = ["5","50","7","51","87","97","53"]
results = list(map(int, numlists))
results.sort(reverse=False)
print(results)

-1

реальна проблема полягає в тому, що сортування сортує речі буквено-цифровими. Отже, якщо у вас є список ['1', '2', '10', '19'] і запустіть сортування, ви отримаєте ['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 --- 010,011--100, 101 і т.д.


-5
scores = ['91','89','87','86','85']
scores.sort()
print (scores)

Це працювало для мене, використовуючи версію python 3, хоча це не було у версії 2.


3
Спробуйте сортувати з '11 і '100' там, тоді все стане цікавим.
Пенз
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.