2010-05-28 23 views
36

Rozważ listę w języku Python: my_list zawierająca ['foo', 'foo', 'bar'].Jaki jest najczystszy sposób sortowania plus uniq na liście Pythona?

Jaki jest najbardziej Pythonowy sposób na uniquify i posortować listę?
(myśl cat my_list | sort | uniq)

Tak właśnie to robię i chociaż działa, jestem pewien, że są lepsze sposoby na zrobienie tego.

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() 
+0

Możliwe duplikowanie icate [Jak usunąć duplikaty z listy Pythona i zachować kolejność?] (http://stackoverflow.com/questions/479897/how-to-remove-duplicates-from-python-list-and-keep-order) – sampablokuper

Odpowiedz

73
my_list = sorted(set(my_list)) 
+9

Uwaga że działa to tylko dla plików typu "hashable", więc na przykład nie będzie działać na listach. – taleinat

+0

Warto wspomnieć, że robi to wszystko w pamięci, podczas gdy "sort" (zwykle?) Wie, że trwa na dysku. Jeśli aplikujesz to do dużej części danych, powinna ona zawieść w 'MemoryError'. Dobra odpowiedź: :) –

+0

@ReutSharabani: Nie, różnica polega na tym, że metoda 'sort()' działa w miejscu i nie wymaga dodatkowej alokacji. –

-4

Nie można powiedzieć, że jest czysty sposób to zrobić, ale tylko dla zabawy:

my_list = [x for x in sorted(my_list) if not x in locals()["_[1]"]] 
+6

To jest brzydkie, magiczne i niepotrzebnie kwadratowe. –

+0

Oczywiście, jest to po prostu dla zabawy, jak zauważyłem. – andreypopp

5

Prosta rozwiązanie zapewnia Ignacio- sorted(set(foo)).

Jeśli masz unikatowe dane, istnieje uzasadniona szansa, że ​​nie chcesz po prostu zrobić sorted(set(...)), ale raczej przechowywać zestaw przez cały czas i od czasu do czasu wyciągać posortowaną wersję wartości. (W tym momencie zaczyna się wydawać coś w rodzaju tego, do czego ludzie często używają bazy danych).

Jeśli masz posortowaną listę i chcesz sprawdzić członkostwo na logarytmicznym i dodaj pozycję w najgorszym przypadku czas liniowy , możesz użyć bisect module.

Jeśli chcesz zachować ten stan przez cały czas, a chcesz uprościć pewne czynności lub sprawić, że niektóre operacje będą działać lepiej, możesz rozważyć blist.sortedset.

+0

Rozważ [sortowane kontenery] (http://www.grantjenks.com/docs/sortedcontainers/). [SortedSet] (http://www.grantjenks.com/docs/sortedcontainers/sortedset.html) zamiast blist. Jest to [szybsze] (http://www.grantjenks.com/docs/sortedcontainers/performance.html) i czysty-Python. – GrantJ

2

Inni wspomnieli o posortowaniu (set (moja_lista)), który działa na nieaktualne wartości, takie jak łańcuchy, liczby i krotki, ale nie dla typów nieodmiennych, takich jak listy.

Aby uzyskać posortowaną listę wartości dowolnego typu sortable, bez duplikatów:

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 

ten może być dalej uproszczone za pomocą „parami” lub „unique_justseen” recepty z itertools documentation.

10
# 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))) 

Szybsze:

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

Obie wersje powrót generator, więc może chcesz podać wynik do typu listy:

sequence= list(sort_uniq(sequence)) 

Zauważ, że to będzie działać z nie- elementy podlegające ujednoliceniu:

>>> list(sort_uniq([[0],[1],[0]])) 
[[0], [1]] 
+1

Jeśli korzystasz z mapy python3: Py3 iw Py2 itertools.imap robisz dokładnie to samo. (W Py3 iter (mapa (...)) jest zbędny.) –

+0

To znacznie lepiej niż przyjęta odpowiedź, zakładając, że masz dużą porcję danych. +1 –

+0

@TheDemz odpowiedź potrzebna, biorąc pod uwagę, że Python 3 jest teraz bardziej powszechny niż wtedy; dzięki – tzot

Powiązane problemy