Bagaimana cara mengurutkan daftar string secara numerik?

128

Saya tahu bahwa ini terdengar sepele tetapi saya tidak menyadari bahwa sort()fungsi Python itu aneh. Saya memiliki daftar "angka" yang sebenarnya dalam bentuk string, jadi saya mengonversinya terlebih dahulu menjadi int, kemudian mencoba mengurutkan.

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

list1.sort()
print list1

Memberi saya:

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

Yang saya inginkan adalah

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

Saya telah melihat-lihat beberapa algoritma yang terkait dengan pengurutan set numerik, tetapi yang saya temukan semuanya melibatkan pengurutan set alfanumerik.

Saya tahu ini mungkin masalah yang tidak perlu dipikirkan, tetapi google dan buku teks saya tidak menawarkan sesuatu yang lebih atau kurang berguna daripada .sort()fungsinya.

Brian
sumber
9
Perhatikan bahwa perulangan for Anda tidak melakukan apa yang saya duga seperti yang Anda pikirkan.
deinst
1
Anda tidak pernah memperbarui list1. Apa yang membuat Anda berpikir listsedang diperbarui?
S. Lott
Masalah serupa muncul ketika list1 = ['1', '1.10', '1.11', '1.1', '1.2'] disediakan sebagai input. Alih-alih mendapatkan keluaran sebagai ['1', '1.1', '1.2', '1.10', '1.11'], saya mendapatkan ['1', '1.1', '1.10', '1.11', '1.2' ]
sathish
2
dengan python 3 Anda mungkin ingin menggunakansorted(mylist)
Akin Hwan

Jawaban:

191

Anda belum benar-benar mengubah string Anda menjadi int. Atau lebih tepatnya, Anda melakukannya, tetapi kemudian Anda tidak melakukan apa pun dengan hasilnya. Yang Anda inginkan adalah:

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

Jika karena alasan tertentu Anda perlu menyimpan string alih-alih int (biasanya ide yang buruk, tapi mungkin Anda perlu mempertahankan nol di depan atau sesuatu), Anda dapat menggunakan fungsi kunci . sortmengambil parameter bernama key, yang merupakan fungsi yang dipanggil pada setiap elemen sebelum dibandingkan. Nilai yang dikembalikan dari fungsi kunci akan dibandingkan, bukan membandingkan elemen daftar secara langsung:

list1 = ["1","10","3","22","23","4","2","200"]
# call int(x) on each element before comparing it
list1.sort(key=int)
Seamus Campbell
sumber
8
ketika saya mencoba key = int di 2.7 saya mendapatkan None
KI4JGT
1
Ini berfungsi jika elemen daftar disimpan sebagai "integer", bagaimana harus ditangani dalam kasus nilai float? Misalnya, list1 = [1, 1.10, 1.11, 1.1, 1.2]
sathish
1
@ KI4JGT metode pengurutan mengubah daftar dan mengembalikan None. Jadi alih-alih list1 = list1.sort(key=int), gunakan saja list1.sort(key=int)dan list1 sudah akan diurutkan.
Josiah Yoder
1
@ KI4JGT .sort () adalah operator di tempat, ia mengembalikan Tidak ada, itu mengurutkan daftar, Anda mungkin ingin menggunakan diurutkan ()
sherpya
39

Anda bisa melewati fungsi dari keyparameter untuk para .sortmetode . Dengan ini, sistem akan mengurutkan berdasarkan kunci (x), bukan x.

list1.sort(key=int)

BTW, untuk mengubah daftar untuk bilangan bulat secara permanen, gunakan yang mapfungsi

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

atau pemahaman daftar

list1 = [int(x) for x in list1]
kennytm
sumber
21

Jika Anda ingin menggunakan sorted()fungsi:sorted(list1, key=int)

Ini mengembalikan daftar diurutkan baru.

syam
sumber
1
Bekerja dengan set juga!
MT
12

Jenis Python tidak aneh. Hanya saja kode ini:

for item in list1:
   item=int(item)

tidak melakukan apa yang Anda pikirkan - itemtidak diganti kembali ke dalam daftar, tetapi dibuang begitu saja.

Bagaimanapun, solusi yang benar adalah menggunakan key=intseperti yang ditunjukkan orang lain kepada Anda.

Daniel Roseman
sumber
12

Anda juga bisa menggunakan:

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

Ini sangat mirip dengan hal lain yang dapat Anda temukan di internet tetapi juga berfungsi untuk alfanumerik seperti [abc0.1, abc0.2, ...].

Julian
sumber
9

Saya mendekati masalah yang sama kemarin dan menemukan modul bernama [natsort] [1], yang memecahkan masalah Anda. Menggunakan:

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']

Ini juga berfungsi untuk kamus sebagai padanannya sorted. [1]: https://pypi.org/project/natsort/

rfaenger
sumber
8

Jawaban Seamus Campbell tidak berfungsi di python2.x.
list1 = sorted(list1, key=lambda e: int(e))menggunakan lambdafungsi bekerja dengan baik.

Marx Wolf
sumber
3

Coba ini, ini akan mengurutkan daftar di tempat dalam urutan menurun (tidak perlu menentukan kunci dalam kasus ini):

Proses

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

keluaran:

 [48, 46, 25, 24, 22, 13, 8, -9, -15, -36]
Mavia
sumber
0

Solusi terbaru sudah benar. Anda membaca solusi sebagai string, dalam hal ini urutannya adalah 1, lalu 100, lalu 104 diikuti oleh 2 lalu 21, lalu 2001001010, 3, dan seterusnya.

Anda harus CAST masukan Anda sebagai int sebagai gantinya:

string yang diurutkan:

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

int diurutkan:

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

Untuk mentransmisikan, cukup letakkan stringList di dalam int (blahblah).

Lagi:

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

newList = int (stringList)

print newList

=> returns (1, 2, 3, 10, 21) 
clint
sumber
1
TypeError: int () argumen harus berupa string atau angka, bukan 'tuple'
Cees Timmerman
Selain itu, string dalam stringList Anda harus memiliki tanda kutip.
Teepeemm
2
Itu adalah prediksi hebat untuk dibuat: "solusi terbaru adalah benar";)
GreenAsJade
0

Jika Anda ingin menggunakan string angka lebih baik mengambil daftar lain seperti yang ditunjukkan dalam kode saya itu akan berfungsi dengan baik.

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
sumber
0

Cara sederhana untuk mengurutkan daftar numerik

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

Masalah sebenarnya adalah hal semacam itu menyortir hal-hal secara alfanumerik. Jadi jika Anda memiliki daftar ['1', '2', '10', '19'] dan menjalankan urutkan Anda akan mendapatkan ['1', '10'. '19', '2']. yaitu 10 muncul sebelum 2 karena melihat karakter pertama dan mengurutkan mulai dari itu. Tampaknya sebagian besar metode dalam python mengembalikan barang dalam urutan itu. Misalnya jika Anda memiliki direktori bernama abc dengan file berlabel 1.jpg, 2.jpg dll, katakan hingga 15.jpg dan Anda melakukan file_list = os.listdir (abc) file_list tidak diurutkan seperti yang Anda harapkan melainkan sebagai file_list = ['1.jpg', '11 .jpg '---' 15.jpg ',' 2.jpg]. Jika urutan file diproses adalah penting (mungkin karena itulah Anda menamainya secara numerik) urutannya tidak seperti yang Anda pikirkan. Anda dapat menghindari ini dengan menggunakan padding "nol". Misalnya jika Anda memiliki daftar alist = ['01', '03', '05', '10', '02', '04', '06] dan Anda menjalankan sortir di atasnya, Anda mendapatkan urutan yang Anda inginkan. alist = ['01', '02' etc] karena karakter pertama adalah 0 yang muncul sebelum 1. Jumlah padding nol yang Anda butuhkan ditentukan oleh nilai terbesar dalam daftar. Misalnya jika yang terbesar adalah antara 100 dan 1000 Anda perlu memasukkan satu digit sebagai 001, 002 --- 010.011--100, 101 dll.

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

Ini berfungsi untuk saya menggunakan python versi 3, meskipun tidak di versi 2.

Kamal Reddy
sumber
3
Coba urutkan dengan '11 dan '100' di sana, saat itulah segalanya menjadi menarik.
Penz