web-dev-qa-db-fra.com

Comment trier (liste / tuples) des listes / tuples par élément à un index donné?

J'ai des données dans une liste de listes ou une liste de n-uplets, comme ceci:

data = [[1,2,3], [4,5,6], [7,8,9]]
data = [(1,2,3), (4,5,6), (7,8,9)]

Et je veux trier par le 2ème élément du sous-ensemble. Signification, trier par 2,5,8 où 2 provient de (1,2,3), 5 provient de (4,5,6). Quelle est la façon habituelle de faire cela? Devrais-je stocker des n-uplets ou des listes dans ma liste?

545
Stan
sorted_by_second = sorted(data, key=lambda tup: tup[1])

ou:

data.sort(key=lambda tup: tup[1])  # sorts in place
956
Stephen
from operator import itemgetter
data.sort(key=itemgetter(1))
193
manova

Je veux juste ajouter à la réponse de Stephen si vous voulez trier le tableau de haut en bas, une autre manière que dans les commentaires ci-dessus est simplement d'ajouter ceci à la ligne:

reverse = True

et le résultat sera le suivant:

data.sort(key=lambda tup: tup[1], reverse=True)
46
sifoo

Pour le tri selon plusieurs critères, à savoir par exemple les deuxième et troisième éléments d’un tuple,

data = [(1,2,3),(1,2,1),(1,1,4)]

et ainsi définir un lambda qui retourne un tuple qui décrit la priorité, par exemple

sorted(data, key=lambda tup: (tup[1],tup[2]) )
[(1, 1, 4), (1, 2, 1), (1, 2, 3)]
33
elm

la réponse de Stephen est celui que j'utiliserais. Pour être complet, voici le modèle DSU (decorate-sort-undecorate) avec liste des compréhensions:

decorated = [(tup[1], tup) for tup in data]
decorated.sort()
undecorated = [tup for second, tup in decorated]

Ou plus simplement:

[b for a,b in sorted((tup[1], tup) for tup in data)]

Comme indiqué dans le HowTo de Python , cela n’est plus nécessaire depuis Python 2.4, lorsque les fonctions de touche sont devenues disponibles.

27
tcarobruce

Pour trier une liste de tuples (<Word>, <count>), pour count dans l’ordre décroissant et Word dans l’ordre alphabétique:

data = [
('betty', 1),
('bought', 1),
('a', 1),
('bit', 1),
('of', 1),
('butter', 2),
('but', 1),
('the', 1),
('was', 1),
('bitter', 1)]

J'utilise cette méthode:

sorted(data, key=lambda tup:(-tup[1], tup[0]))

et ça me donne le résultat:

[('butter', 2),
('a', 1),
('betty', 1),
('bit', 1),
('bitter', 1),
('bought', 1),
('but', 1),
('of', 1),
('the', 1),
('was', 1)]
16
l mingzhi

Sans lambda:

def sec_elem (s): 
 renvoie s [1] 
trié (données, clé = sec_elem) 
10
Mesco

La réponse de @Stephen va droit au but! Voici un exemple pour une meilleure visualisation,

Criez pour les fans de Ready Player One! =)

>>> gunters = [('2044-04-05', 'parzival'), ('2044-04-07', 'aech'), ('2044-04-06', 'art3mis')]
>>> gunters.sort(key=lambda tup: tup[0])
>>> print gunters
[('2044-04-05', 'parzival'), ('2044-04-06', 'art3mis'), ('2044-04-07', 'aech')]

key est une fonction appelée pour transformer les éléments de la collection à des fins de comparaison. Comme la méthode compareTo en Java.

Le paramètre passé à key doit être un élément appelable. Ici, l'utilisation de lambda crée une fonction anonyme (qui est appelable).
La syntaxe de lambda est le mot lambda suivi d’un nom itérable, puis d’un seul bloc de code.

Dans l'exemple ci-dessous, nous trions une liste de Tuple contenant les informations sur l'heure de certains événements et le nom de l'acteur.

Nous trions cette liste par heure d'occurrence d'événement - qui est le 0ème élément d'un tuple.

Remarque - s.sort([cmp[, key[, reverse]]]) trie les éléments de s en place

6
Rishi

itemgetter() est un peu plus rapide que lambda tup: tup[1], mais l'augmentation est relativement modeste (environ 10 à 25%).

(Session IPython)

>>> from operator import itemgetter
>>> from numpy.random import randint
>>> values = randint(0, 9, 30000).reshape((10000,3))
>>> tpls = [Tuple(values[i,:]) for i in range(len(values))]

>>> tpls[:5]    # display sample from list
[(1, 0, 0), 
 (8, 5, 5), 
 (5, 4, 0), 
 (5, 7, 7), 
 (4, 2, 1)]

>>> sorted(tpls[:5], key=itemgetter(1))    # example sort
[(1, 0, 0), 
 (4, 2, 1), 
 (5, 4, 0), 
 (8, 5, 5), 
 (5, 7, 7)]

>>> %timeit sorted(tpls, key=itemgetter(1))
100 loops, best of 3: 4.89 ms per loop

>>> %timeit sorted(tpls, key=lambda tup: tup[1])
100 loops, best of 3: 6.39 ms per loop

>>> %timeit sorted(tpls, key=(itemgetter(1,0)))
100 loops, best of 3: 16.1 ms per loop

>>> %timeit sorted(tpls, key=lambda tup: (tup[1], tup[0]))
100 loops, best of 3: 17.1 ms per loop
5
Walter