Comment trier une liste de chaînes numériquement?


128

Je sais que cela semble trivial mais je ne savais pas que la sort()fonction de Python était bizarre. J'ai une liste de "nombres" qui sont en fait sous forme de chaîne, donc je les convertis d'abord en entiers, puis j'essaye un tri.

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

list1.sort()
print list1

Donne moi:

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

Ce que je veux c'est

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

J'ai cherché certains des algorithmes associés au tri des ensembles numériques, mais ceux que j'ai trouvés impliquent tous le tri des ensembles alphanumériques.

Je sais que c'est probablement un problème évident, mais Google et mon manuel n'offrent rien de plus ou de moins utile que la .sort()fonction.


9
Notez que votre boucle for ne fait pas ce que je suppose que vous pensez qu'elle fait.
deinst

1
A aucun moment vous n'avez mis à jour list1. Qu'est-ce qui vous a fait penser listque la mise à jour était en cours?
S.Lott

Le problème similaire se pose lorsque list1 = ['1', '1.10', '1.11', '1.1', '1.2'] est fourni en entrée. Au lieu d'obtenir la sortie comme ['1', '1.1', '1.2', '1.10', '1.11'], j'obtiens ['1', '1.1', '1.10', '1.11', '1.2' ]
sathish

2
en python 3, vous voudrez peut-être utilisersorted(mylist)
Akin Hwan

Réponses:


191

Vous n'avez pas réellement converti vos chaînes en entiers. Ou plutôt, vous l'avez fait, mais vous n'avez rien fait avec les résultats. Ce que tu veux c'est:

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

Si, pour une raison quelconque, vous devez conserver des chaînes au lieu des entiers (généralement une mauvaise idée, mais peut-être que vous devez conserver les zéros non significatifs ou quelque chose), vous pouvez utiliser une fonction clé . sortprend un paramètre nommé,, keyqui est une fonction appelée sur chaque élément avant sa comparaison. Les valeurs de retour de la fonction clé sont comparées au lieu de comparer directement les éléments de la liste:

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

8
quand j'essaye key = int dans 2.7, j'obtiens None
KI4JGT

1
Cela fonctionne si l'élément de la liste est stocké en tant que "entier", comment doit-il être géré en cas de valeurs flottantes? Par exemple, list1 = [1, 1.10, 1.11, 1.1, 1.2]
sathish

1
@ KI4JGT la méthode de tri modifie la liste et renvoie None. Donc, au lieu de list1 = list1.sort(key=int), utilisez juste list1.sort(key=int)et list1 sera déjà trié.
Josiah Yoder

1
@ KI4JGT .sort () est un opérateur sur place, il renvoie None, il trie la liste, vous pouvez utiliser
sorted

39

Vous pouvez passer une fonction au keyparamètre à la .sortméthode . Avec cela, le système triera par clé (x) au lieu de x.

list1.sort(key=int)

BTW, pour convertir la liste en nombres entiers de manière permanente, utilisez la mapfonction

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

ou compréhension de liste

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

21

Si vous souhaitez utiliser la sorted()fonction:sorted(list1, key=int)

Il renvoie une nouvelle liste triée.


1
Fonctionne aussi avec des ensembles!
MT

12

Le genre de Python n'est pas bizarre. C'est juste que ce code:

for item in list1:
   item=int(item)

ne fait pas ce que vous pensez que c'est - itemn'est pas replacé dans la liste, il est simplement jeté.

Quoi qu'il en soit, la bonne solution est d'utiliser key=intcomme d'autres vous l'ont montré.


12

Vous pouvez aussi utiliser:

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

Ceci est très similaire à d'autres choses que vous pouvez trouver sur Internet, mais fonctionne également pour les alphanumériques comme [abc0.1, abc0.2, ...].


9

J'ai abordé le même problème hier et j'ai trouvé un module appelé [natsort] [1], qui résout votre problème. Utilisation:

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

Il fonctionne également pour les dictionnaires comme un équivalent de sorted. [1]: https://pypi.org/project/natsort/


8

La réponse de Seamus Campbell ne fonctionne pas sur python2.x.
list1 = sorted(list1, key=lambda e: int(e))l'utilisation de la lambdafonction fonctionne bien.


3

Essayez ceci, cela triera la liste sur place par ordre décroissant (il n'est pas nécessaire de spécifier une clé dans ce cas):

Processus

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

production:

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

0

La solution la plus récente est la bonne. Vous lisez les solutions sous forme de chaîne, auquel cas l'ordre est 1, puis 100, puis 104 suivi de 2 puis 21, puis 2001001010, 3 et ainsi de suite.

Vous devez CAST votre entrée comme un int à la place:

chaînes triées:

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

ints triés:

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

Pour lancer, mettez simplement la stringList à l'intérieur de int (blahblah).

Encore:

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

newList = int (stringList)

print newList

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

1
TypeError: l'argument int () doit être une chaîne ou un nombre, pas un 'tuple'
Cees Timmerman

En outre, les chaînes de votre stringList doivent avoir des guillemets.
Teepeemm

2
C'est une prédiction infernale à faire: "la solution la plus récente est la bonne";)
GreenAsJade

0

Si vous souhaitez utiliser des chaînes de nombres, mieux vaut prendre une autre liste comme indiqué dans mon code, cela fonctionnera 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

Un moyen simple de trier une liste numérique

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

-1

Le vrai problème est que le tri trie les choses par ordre alphanumérique. Donc, si vous avez une liste ['1', '2', '10', '19'] et exécutez sort, vous obtenez ['1', '10'. «19», «2»]. c'est-à-dire que 10 vient avant 2 car il regarde le premier caractère et trie à partir de cela. Il semble que la plupart des méthodes en python retournent les choses dans cet ordre. Par exemple, si vous avez un répertoire nommé abc avec les fichiers étiquetés comme 1.jpg, 2.jpg etc., dites jusqu'à 15.jpg et que vous faites file_list = os.listdir (abc), la file_list n'est pas ordonnée comme vous le souhaitez mais plutôt comme file_list = ['1.jpg', '11 .jpg '---' 15.jpg ',' 2.jpg]. Si l'ordre dans lequel les fichiers sont traités est important (c'est probablement pour cela que vous les avez nommés numériquement), l'ordre n'est pas ce que vous pensez qu'il sera. Vous pouvez éviter cela en utilisant un remplissage "zéros". Par exemple, si vous avez une liste alist = ['01', '03', '05', '10', '02', '04', '06] et que vous exécutez le tri dessus, vous obtenez l'ordre souhaité. alist = ['01', '02' etc] car le premier caractère est 0 qui précède 1. La quantité de zéros dont vous avez besoin est déterminée par la plus grande valeur de la liste. Par exemple, si la plus grande est comprise entre 100 et 100. 1000, vous devez remplir des chiffres uniques comme 001, 002 --- 010,011--100, 101 etc.


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

Cela a fonctionné pour moi en utilisant la version 3 de python, bien que ce ne soit pas le cas dans la version 2.


3
Essayez de trier avec «11» et «100», c'est là que les choses deviennent intéressantes.
Penz
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.