¿Cómo ordenar una lista de cadenas numéricamente?

128

Sé que esto suena trivial, pero no me di cuenta de que la sort()función de Python era extraña. Tengo una lista de "números" que en realidad están en forma de cadena, por lo que primero los convierto en ints, luego intento ordenarlos.

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

list1.sort()
print list1

Me da

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

Lo que quiero es

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

He buscado algunos de los algoritmos asociados con la ordenación de conjuntos numéricos, pero los que encontré implican la ordenación de conjuntos alfanuméricos.

Sé que esto probablemente no sea un problema obvio, pero Google y mi libro de texto no ofrecen nada más o menos útil que la .sort()función.

Brian
fuente
9
Tenga en cuenta que su bucle for no hace lo que sospecho que cree que hace.
deinst
1
En ningún momento actualizaste list1. ¿Qué te hizo pensar que listse estaba actualizando?
S.Lott
El problema similar surge cuando list1 = ['1', '1.10', '1.11', '1.1', '1.2'] se proporciona como entrada. En lugar de obtener la salida como ['1', '1.1', '1.2', '1.10', '1.11'], obtengo ['1', '1.1', '1.10', '1.11', '1.2' ]
sathish
2
en python 3 puede utilizarsorted(mylist)
Akin Hwan

Respuestas:

191

En realidad no has convertido tus cadenas en ints. O más bien, lo hiciste, pero luego no hiciste nada con los resultados. Lo que quieres es:

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

Si por alguna razón necesita mantener cadenas en lugar de entradas (generalmente es una mala idea, pero tal vez necesite preservar los ceros iniciales o algo así), puede usar una función de tecla . sorttoma un parámetro con nombre key, que es una función que se llama en cada elemento antes de compararlo. Los valores de retorno de la función clave se comparan en lugar de comparar los elementos de la lista directamente:

list1 = ["1","10","3","22","23","4","2","200"]
# call int(x) on each element before comparing it
list1.sort(key=int)
Seamus Campbell
fuente
8
cuando intento key = int en 2.7 obtengo None
KI4JGT
1
Esto funciona si el elemento de la lista se almacena como "entero", ¿cómo se manejará en caso de valores flotantes? Por ejemplo, list1 = [1, 1.10, 1.11, 1.1, 1.2]
sathish
1
@ KI4JGT, el método de clasificación modifica la lista y devuelve Ninguno. Entonces, en lugar de list1 = list1.sort(key=int)usar just list1.sort(key=int)y list1 ya estará ordenado.
Josiah Yoder
1
@ KI4JGT .sort () es un operador en el lugar, devuelve Ninguno, ordena la lista, puede usar sorted ()
sherpya
39

Se podía pasar una función a la keyparámetro para el .sortmétodo . Con esto, el sistema ordenará por clave (x) en lugar de x.

list1.sort(key=int)

Por cierto, para convertir la lista a enteros de forma permanente, use la mapfunción

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

o lista de comprensión

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

En caso de que quiera usar la sorted()función:sorted(list1, key=int)

Devuelve una nueva lista ordenada.

syam
fuente
1
¡Funciona con sets también!
MT
12

El tipo de Python no es raro. Es solo que este código:

for item in list1:
   item=int(item)

no está haciendo lo que crees que es, itemno se reemplaza de nuevo en la lista, simplemente se descarta.

De todos modos, la solución correcta es usar key=intcomo otros te han mostrado.

Daniel Roseman
fuente
12

También puedes usar:

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

Esto es muy similar a otras cosas que puedes encontrar en Internet, pero también funciona para alfanuméricos como [abc0.1, abc0.2, ...].

Julian
fuente
8

La respuesta de Seamus Campbell no funciona en python2.x.
list1 = sorted(list1, key=lambda e: int(e))El uso de la lambdafunción funciona bien.

Marx Wolf
fuente
8

Ayer abordé el mismo problema y encontré un módulo llamado [natsort] [1], que resuelve su problema. Utilizar:

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

También funciona para diccionarios como un equivalente de sorted. [1]: https://pypi.org/project/natsort/

rfaenger
fuente
3

Pruebe esto, ordenará la lista en el lugar en orden descendente (no es necesario especificar una clave en este caso):

Proceso

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

salida:

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

La solución más reciente es la correcta. Está leyendo soluciones como una cadena, en cuyo caso el orden es 1, luego 100, luego 104 seguido de 2, luego 21, luego 2001001010, 3 y así sucesivamente.

Tienes que CASTAR tu entrada como int en su lugar:

cuerdas clasificadas:

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

entradas ordenadas:

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

Para lanzar, simplemente coloque la cadenaLista dentro de int (blahblah).

De nuevo:

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

newList = int (stringList)

print newList

=> returns (1, 2, 3, 10, 21) 
clint
fuente
1
TypeError: el argumento int () debe ser una cadena o un número, no 'tupla'
Cees Timmerman
Además, las cadenas de su stringList deben tener comillas.
Teepeemm
2
Esa es una predicción infernal: "la solución más reciente es la correcta";)
GreenAsJade
0

Si desea usar cadenas de números, tome otra lista como se muestra en mi código, funcionará bien.

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

Manera simple de ordenar una lista numérica

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

El verdadero problema es que ese tipo clasifica las cosas de forma alfanumérica. Entonces, si tiene una lista ['1', '2', '10', '19'] y ejecuta sort obtendrá ['1', '10'. '19', '2']. es decir, 10 viene antes que 2 porque mira el primer personaje y ordena a partir de eso. Parece que la mayoría de los métodos en Python devuelven las cosas en ese orden. Por ejemplo, si tiene un directorio llamado abc con los archivos etiquetados como 1.jpg, 2.jpg, etc., diga hasta 15.jpg y haga file_list = os.listdir (abc), la file_list no está ordenada como esperaba, sino más bien como file_list = ['1.jpg', '11 .jpg '---' 15.jpg ',' 2.jpg]. Si el orden en que se procesan los archivos es importante (presumiblemente por eso los nombró numéricamente), el orden no es lo que cree que será. Puede evitar esto utilizando el relleno "ceros". Por ejemplo, si tiene una lista alist = ['01', '03', '05', '10', '02', '04', '06] y ejecuta sort en ella, obtiene el orden que deseaba. alist = ['01', '02', etc.] porque el primer carácter es 0 que viene antes que 1. La cantidad de ceros que necesita está determinada por el valor más grande en la lista. Por ejemplo, si el más grande es entre 100 y 1000 necesita rellenar dígitos individuales como 001, 002 --- 010,011--100, 101 etc.

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

Esto funcionó para mí usando Python versión 3, aunque no lo hizo en la versión 2.

Kamal Reddy
fuente
3
Intenta ordenar con '11 y '100' allí, ahí es cuando las cosas se ponen interesantes.
Penz