web-dev-qa-db-fra.com

Trier une liste de tuples par 2ème élément (valeur entière)

J'ai une liste de tuples qui ressemble à ceci:

[('abc', 121),('abc', 231),('abc', 148), ('abc',221)]

Je veux trier cette liste dans l'ordre croissant par la valeur entière à l'intérieur des n-uplets. C'est possible?

358
Amyth

Essayez d’utiliser le mot clé key avec sorted().

sorted([('abc', 121),('abc', 231),('abc', 148), ('abc',221)], key=lambda x: x[1])

key devrait être une fonction qui identifie comment extraire l'élément comparable de votre structure de données. Dans votre cas, il s’agit du deuxième élément du tuple, nous avons donc accès à [1].

Pour une optimisation, voir la réponse de jamylak en utilisant itemgetter(1), qui est essentiellement une version plus rapide de lambda x: x[1].

554
cheeken
>>> from operator import itemgetter
>>> data = [('abc', 121),('abc', 231),('abc', 148), ('abc',221)]
>>> sorted(data,key=itemgetter(1))
[('abc', 121), ('abc', 148), ('abc', 221), ('abc', 231)]

IMO utilisant itemgetter est plus lisible que la solution de @cheeken. Il est également plus rapide puisque la quasi-totalité du calcul se fera du côté c (sans jeu de mots) plutôt que par l’utilisation de lambda.

>python -m timeit -s "from operator import itemgetter; data = [('abc', 121),('abc', 231),('abc', 148), ('abc',221)]" "sorted(data,key=itemgetter(1))"
1000000 loops, best of 3: 1.22 usec per loop

>python -m timeit -s "data = [('abc', 121),('abc', 231),('abc', 148), ('abc',221)]" "sorted(data,key=lambda x: x[1])"
1000000 loops, best of 3: 1.4 usec per loop
186
jamylak

En tant que néophyte python, je voulais simplement mentionner que si les données ressemblaient réellement à ceci:

data = [('abc', 121),('abc', 231),('abc', 148), ('abc',221)]

alors sorted() triera automatiquement en fonction du deuxième élément du tuple, car les premiers éléments sont tous identiques.

39
Angus

Ajoutant à la réponse de Cheeken, voici comment trier une liste de n-uplets par le 2e élément dans ordre décroissant.

sorted([('abc', 121),('abc', 231),('abc', 148), ('abc',221)],key=lambda x: x[1], reverse=True)
38
Vignesh Jayavel

De python wiki:

>>> from operator import itemgetter, attrgetter    
>>> sorted(student_tuples, key=itemgetter(2))
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]    
>>> sorted(student_objects, key=attrgetter('age'))
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
14

Pour un tri sur place, utilisez

foo = [(list of tuples)]
foo.sort(key=lambda x:x[0]) #To sort by first element of the Tuple
12
Shivank Tibrewal

Pour une méthode évitant le lambda, commencez par définir votre propre fonction:

def MyFn(a):
    return a[1]

ensuite:

sorted([('abc', 121),('abc', 231),('abc', 148), ('abc',221)], key=MyFn)
8
paulm

Pour Python 2.7+, cela fonctionne, ce qui rend la réponse acceptée légèrement plus lisible:

sorted([('abc', 121),('abc', 231),('abc', 148), ('abc',221)], key=lambda (k, val): val)
3
Neil

Le fait que les valeurs de tri dans l'OP soient des entiers n'est pas pertinent pour la question en soi. En d'autres termes, la réponse acceptée fonctionnerait si la valeur de tri était du texte. Je soulève cette question afin de préciser que le tri peut être modifié au cours du tri (par exemple, pour tenir compte des majuscules et des minuscules).

>>> sorted([(121, 'abc'), (231, 'def'), (148, 'ABC'), (221, 'DEF')], key=lambda x: x[1])
[(148, 'ABC'), (221, 'DEF'), (121, 'abc'), (231, 'def')]
>>> sorted([(121, 'abc'), (231, 'def'), (148, 'ABC'), (221, 'DEF')], key=lambda x: str.lower(x[1]))
[(121, 'abc'), (148, 'ABC'), (231, 'def'), (221, 'DEF')]
0
DaveL17