¿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.


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)

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]

21

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

Devuelve una nueva lista ordenada.


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.


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, ...].


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.


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/


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]

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) 

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]

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)

-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.


-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.


3
Intenta ordenar con '11 y '100' allí, ahí es cuando las cosas se ponen interesantes.
Penz
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.