2015-07-17 18 views
5

Mam dyktować listy i potrzebuję szybkiego sposobu na dedupe list.Najszybszy sposób dedupe listy w dyktafonie

Wiem, jak dedupe listę w izolacji za pomocą funkcji set(), ale w tym przypadku chcę szybki sposób iteracji przez dykt, deduputując każdą listę na drodze.

hello = {'test1':[2,3,4,2,2,5,6], 'test2':[5,5,8,4,3,3,8,9]} 

Chciałbym, żeby wyglądało jak;

hello = {'test1':[2,3,4,5,6], 'test2':[5,8,4,3,9]} 

Chociaż niekoniecznie muszę mieć zachowany pierwotny porządek list.

Próbowałem przy użyciu zestawu takiego, ale nie jest to całkiem poprawne (nie jest iteracja prawidłowo i tracę pierwszy klucz)

for key, value in hello.items(): goodbye = {key: set(value)} 
>>> goodbye 
{'test2': set([8, 9, 3, 4, 5])} 

EDIT: Po komentarza premiera 2Ring jest poniżej, Teraz zapełniam dyktando inaczej, niż unikam duplikatów. Poprzednio używałem list, ale używanie zestawów zapobiega domyślnemu dodawaniu duplikatów;

>>> my_numbers = {} 
>>> my_numbers['first'] = [1,2,2,2,6,5] 
>>> from collections import defaultdict 
>>> final_list = defaultdict(set) 
>>> for n in my_numbers['first']: final_list['test_first'].add(n) 
... 
>>> final_list['test_first'] 
set([1, 2, 5, 6]) 

Jak widać, ostateczne wyjście jest zbiorem dedupowanym, zgodnie z wymaganiami.

+2

Nie interesuje porządek zachowania, a także moje listy są część dyktatu. –

+2

Jeśli nie zachowujesz porządku, wybierz podejście oparte na zestawie: jest to bardziej efektywne niż podejście oparte na listach, ale możesz zauważyć różnicę prędkości, jeśli twoje listy są małe lub mają niewiele duplikatów . I rozważ przechowywanie zestawów zamiast list jako wartości twojego dyktatora. OTOH, dla "małych" małych list, metoda oparta na zestawie może być "wolniejsza". Ponadto zestawy używają trochę więcej pamięci niż listy. –

+0

@ PM2Ring Poszedłem z użyciem zestawów na końcu, więc w pierwszej kolejności uniknąłem duplikatów. defaultdict (set) i .add (n) do dołączenia do zestawu zrobiły lewę. Q zaktualizowany. –

Odpowiedz

4

To nie iteracja źle, jesteś po prostu przypisanie do widzenia jako nowy dict każdym razem. Musisz przypisać jako pusty dict, a następnie przypisać wartości do kluczy w każdej iteracji.

goodbye = {} 
for key, value in hello.items(): goodbye[key] = set(value) 
>>> goodbye 
{'test1': set([2, 3, 4, 5, 6]), 'test2': set([8, 9, 3, 4, 5])} 

Ponadto, ponieważ zbiory nie zachować porządek, jeśli chce zachować porządek to najlepiej zrobić prostą funkcję iteracji że powróci nową listę, która pomija już wartości dodanych.

def uniqueList(li): 
    newList = [] 
    for x in li: 
     if x not in newList: 
      newList.append(x) 
    return newList 


goodbye = {} 
for key, value in hello.items(): goodbye[key] = uniqueList(value) 
>>> goodbye 
{'test1': [2, 3, 4, 5, 6], 'test2': [5, 8, 4, 3, 9]} 
+1

Sądzę, że to jeden z powodów, dla których OP powiedział, że jego rozwiązanie jest "nie do końca poprawne", a kolejność jest zachowywana na listach (!) W oczekiwanym wyniku. –

+0

OP tutaj. W rzeczywistości zachowanie kolejności nie ma znaczenia. Tak więc to podejście działa dobrze również dla moich celów. Moje rozwiązanie nie było całkiem poprawne, ponieważ przypisałem nową wartość zamiast dodawać, pozostawiając sobie tylko jeden klucz. –

+0

W każdym razie, dla zachowania kompletności, dodaliśmy drugie rozwiązanie do konserwowania. – SuperBiasedMan

5

Można użyć wyrażeń listowych z deduplicate funkcji, która zachowuje kolejność:

def deduplicate(seq): 
    seen = set() 
    seen_add = seen.add 
    return [ x for x in seq if not (x in seen or seen_add(x))] 

{key: deduplicate(value) for key, value in hello.items()} 
+0

Tak jak w notatce: Zrozumienia dict nie działają ze starszymi wersjami Pythona, takimi jak 2.7. – Daniel

+1

@Daniel działa w Pythonie 2.7, nie działa w żadnej starszej wersji. –

+0

@AnandSKumar Masz rację. Zepsułem to. – Daniel

0

Jest to bardziej rozwlekły sposób z tym, który zachowuje porządek i działa we wszystkich wersjach Pythona:

for key in hello: 
    s = set() 
    l = [] 
    for subval in hello[key]: 
     if subval not in s: 
      l.append(subval) 
      s.add(subval) 
    hello[key] = l 
0
my_list = [1,2,2,2,3,4,5,6,7,7,7,7,7,8,9,10] 
seen = set() 
print list(filter(lambda x:x not in seen and not seen.add(x),my_list)) 
3
>>>hello = {'test1':[2,3,4,2,2,5,6], 'test2':[5,5,8,4,3,3,8,9]}  
>>>for key,value in hello.iteritems(): 
     hello[key] = list(set(value)) 
>>>hello 
{'test1': [2, 3, 4, 5, 6], 'test2': [8, 9, 3, 4, 5]} 
+1

Ah cool, który zmienia zestaw z powrotem na listę. –

Powiązane problemy