Come ordinare numericamente un elenco di stringhe?


128

So che suona banale ma non mi ero reso conto che la sort()funzione di Python fosse strana. Ho un elenco di "numeri" che sono effettivamente in forma di stringa, quindi li converto prima in interi, quindi provo a eseguire un ordinamento.

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

list1.sort()
print list1

Mi da:

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

Quello che voglio è

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

Ho cercato alcuni degli algoritmi associati all'ordinamento di set numerici, ma quelli che ho trovato riguardano tutti l'ordinamento di set alfanumerici.

So che questo è probabilmente un problema semplicissimo, ma Google e il mio libro di testo non offrono nulla di più o meno utile della .sort()funzione.


9
Nota che il tuo ciclo for non fa quello che sospetto tu pensi che faccia.
dal

1
In nessun momento hai aggiornato list1. Cosa ti ha fatto pensare che listfosse in fase di aggiornamento?
S.Lott

Il problema simile sorge quando list1 = ['1', '1.10', '1.11', '1.1', '1.2'] viene fornito come input. Invece di ottenere l'output come ["1", "1.1", "1.2", "1.10", "1.11"], ottengo ["1", "1.1", "1.10", "1.11", "1.2" ]
satish

2
in python 3 potresti voler usaresorted(mylist)
Akin Hwan

Risposte:


191

Non hai effettivamente convertito le tue stringhe in int. O meglio, l'hai fatto, ma poi non hai fatto nulla con i risultati. Quello che vuoi è:

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

Se per qualche motivo hai bisogno di mantenere le stringhe invece degli interi (di solito una cattiva idea, ma forse hai bisogno di preservare gli zeri iniziali o qualcosa del genere), puoi usare una funzione chiave . sortaccetta un parametro denominato,, keyche è una funzione che viene chiamata su ogni elemento prima di essere confrontato. I valori restituiti dalla funzione chiave vengono confrontati invece di confrontare direttamente gli elementi dell'elenco:

list1 = ["1","10","3","22","23","4","2","200"]
# call int(x) on each element before comparing it
list1.sort(key=int)

8
quando provo key = int in 2.7 ottengo Nessuno
KI4JGT

1
Funziona se l'elemento della lista è memorizzato come "intero", come deve essere gestito in caso di valori float? Ad esempio, list1 = [1, 1.10, 1.11, 1.1, 1.2]
sathish

1
@ KI4JGT il metodo di ordinamento modifica l'elenco e restituisce Nessuno. Quindi, invece di list1 = list1.sort(key=int), usa solo list1.sort(key=int)e list1 sarà già ordinato.
Josiah Yoder,

1
@ KI4JGT .sort () è un operatore sul posto, restituisce Nessuno, ordina l'elenco, potresti voler usare ordinato ()
sherpya

39

Si potrebbe passare una funzione al keyparametro del .sortmetodo . Con questo, il sistema ordinerà per chiave (x) invece di x.

list1.sort(key=int)

BTW, per convertire l'elenco in interi in modo permanente, utilizzare la mapfunzione

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

o comprensione delle liste

list1 = [int(x) for x in list1]

21

Nel caso in cui desideri utilizzare la sorted()funzione:sorted(list1, key=int)

Restituisce un nuovo elenco ordinato.


1
Funziona anche con i set!
MT

12

Il tipo di Python non è strano. È solo che questo codice:

for item in list1:
   item=int(item)

non sta facendo quello che pensi - itemnon viene rimpiazzato nell'elenco, viene semplicemente gettato via.

Ad ogni modo, la soluzione corretta è usare key=intcome altri ti hanno mostrato.


12

Puoi anche usare:

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

Questo è molto simile ad altre cose che puoi trovare su Internet, ma funziona anche per gli alfanumerici come [abc0.1, abc0.2, ...].


9

Ho affrontato lo stesso problema ieri e ho trovato un modulo chiamato [natsort] [1], che risolve il tuo problema. Uso:

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

Funziona anche per i dizionari come equivalente di sorted. [1]: https://pypi.org/project/natsort/


8

La risposta di Seamus Campbell non funziona su python2.x.
list1 = sorted(list1, key=lambda e: int(e))usare la lambdafunzione funziona bene.


3

Prova questo, ordinerà l'elenco sul posto in ordine decrescente (non è necessario specificare una chiave in questo caso):

Processi

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

produzione:

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

0

La soluzione più recente è giusta. Stai leggendo le soluzioni come una stringa, nel qual caso l'ordine è 1, quindi 100, quindi 104 seguito da 2, 21, quindi 2001001010, 3 e così via.

Devi invece CAST il tuo input come int:

stringhe ordinate:

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

int ordinati:

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

Per eseguire il cast, metti semplicemente stringList all'interno di int (blahblah).

Ancora:

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

newList = int (stringList)

print newList

=> returns (1, 2, 3, 10, 21) 

1
TypeError: l'argomento int () deve essere una stringa o un numero, non "tupla"
Cees Timmerman

Inoltre, le stringhe nella tua stringList dovrebbero contenere virgolette.
Teepeemm

2
Questa è una previsione infernale da fare: "la soluzione più recente è giusta";)
GreenAsJade,

0

Se vuoi usare le stringhe dei numeri meglio prendere un altro elenco come mostrato nel mio codice funzionerà bene.

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

Modo semplice per ordinare un elenco numerico

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

-1

il vero problema è che l'ordinamento ordina le cose in modo alfanumerico. Quindi, se hai una lista ["1", "2", "10", "19"] ed esegui sort, ottieni ["1", "10". "19", "2"]. cioè 10 viene prima di 2 perché guarda al primo carattere e ordina a partire da quello. Sembra che la maggior parte dei metodi in Python restituisca le cose in quest'ordine. Ad esempio, se hai una directory chiamata abc con i file etichettati come 1.jpg, 2.jpg ecc. Dì fino a 15.jpg e fai file_list = os.listdir (abc) il file_list non è ordinato come ti aspetti ma piuttosto come file_list = ["1.jpg", "11 .jpg "---" 15.jpg "," 2.jpg]. Se l'ordine in cui i file vengono elaborati è importante (presumibilmente è per questo che li hai nominati numericamente), l'ordine non è quello che pensi che sarà. È possibile evitarlo utilizzando il riempimento "zeri". Ad esempio, se hai una lista alist = ['01', '03', '05', '10', '02', '04', '06] e esegui l'ordinamento su di essa, ottieni l'ordine che desideri. alist = ['01', '02' ecc] perché il primo carattere è 0 che viene prima di 1. La quantità di riempimento di zeri di cui hai bisogno è determinata dal valore più grande nell'elenco. Ad esempio, se il più grande è compreso tra 100 e 1000 devi inserire una sola cifra come 001, 002 --- 010,011--100, 101 ecc.


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

Questo ha funzionato per me usando Python versione 3, anche se non nella versione 2.


3
Prova a ordinare con "11" e "100", ecco quando le cose si fanno interessanti.
Penz
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.