Considérons une Python my_list
contenant ['foo', 'foo', 'bar']
.
Quelle est la façon la plus pythonique de niquify et de trier une liste?
(pense cat my_list | sort | uniq
)
C'est ainsi que je le fais actuellement et bien que cela fonctionne, je suis sûr qu'il existe de meilleures façons de le faire.
my_list = []
...
my_list.append("foo")
my_list.append("foo")
my_list.append("bar")
...
my_list = set(my_list)
my_list = list(my_list)
my_list.sort()
my_list = sorted(set(my_list))
# Python ≥ 2.4
# because of (generator expression) and itertools.groupby, sorted
import itertools
def sort_uniq(sequence):
return (x[0] for x in itertools.groupby(sorted(sequence)))
Plus rapide:
import itertools, operator
import sys
if sys.hexversion < 0x03000000:
mapper= itertools.imap # 2.4 ≤ Python < 3
else:
mapper= map # Python ≥ 3
def sort_uniq(sequence):
return mapper(
operator.itemgetter(0),
itertools.groupby(sorted(sequence)))
Les deux versions renvoient un générateur, vous pouvez donc vouloir fournir le résultat au type de liste:
sequence= list(sort_uniq(sequence))
Notez que cela fonctionnera également avec les articles non hachables:
>>> list(sort_uniq([[0],[1],[0]]))
[[0], [1]]
La solution simple est fournie par Ignacio —sorted(set(foo))
.
Si vous avez des données uniques, il y a une chance raisonnable que vous ne souhaitiez pas simplement faire sorted(set(...))
mais plutôt stocker un ensemble tout le temps et parfois extraire une version triée des valeurs. (À ce stade, cela commence à ressembler au genre de chose pour laquelle les gens utilisent souvent une base de données.)
Si vous avez une liste triée et que vous voulez vérifier l'appartenance sur logarithmique et ajouter un élément dans le pire des cas, le temps linéaire, vous pouvez utiliser le module bisect
.
Si vous souhaitez conserver cette condition tout le temps et que vous souhaitez simplifier les choses ou améliorer le fonctionnement de certaines opérations, vous pouvez envisager blist.sortedset
.
D'autres ont mentionné trié (set (ma_liste)), qui fonctionne pour les valeurs lavables telles que les chaînes, les nombres et les tuples, mais pas pour les types non lavables tels que les listes.
Pour obtenir une liste triée de valeurs de tout type triable, sans doublons:
from itertools import izip, islice
def unique_sorted(values):
"Return a sorted list of the given values, without duplicates."
values = sorted(values)
if not values:
return []
consecutive_pairs = izip(values, islice(values, 1, len(values)))
result = [a for (a, b) in consecutive_pairs if a != b]
result.append(values[-1])
return result
Cela peut être encore simplifié en utilisant les recettes "par paire" ou "unique_justseen" de la documentation itertools .