2011-08-04 17 views
5

Muszę dołączyć elementy do listy tylko wtedy, gdy bieżący iterowany element nie znajduje się jeszcze na liście.Czy rozumienie list jest tutaj odpowiednie?

>>> l = [1, 2] 
>>> for x in (2, 3, 4): 
...  if x not in l: 
...    l.append(x) 
... 
>>> l 
[1, 2, 3, 4] 

vs

>>> l = [1, 2] 
>>> [l.append(i) for i in (2, 3, 4) if i not in l] 
[None, None] 
>>> l 
[1, 2, 3, 4] 

Lista rozumienie daje wynik jest to, co chcę, tylko wrócił lista jest bezużyteczne. Czy jest to dobry przypadek do zrozumienia list?

Ta iteracja to dobre rozwiązanie, ale zastanawiam się, czy istnieje bardziej idiomatyczny sposób na zrobienie tego?

+0

Z jakiegoś powodu nie mogę ponownie edytować mojego pytania. Zapomniałem powiedzieć, że zależy mi na porządku elementów. – Paolo

+0

W codziennym użyciu będę musiał pośredniczyć między proponowanymi rozwiązaniami. Gerrat's jest kompaktowy, TokenMacGuy jest wyraźny i szybki, podczas gdy Tyz umieszcza się w środku, jest zwarty i szybki, choć mniej bezpośredni. DZIĘKI za wspaniałe odpowiedzi. Sprawdziłem odpowiedź Gerrata, ponieważ jest bliższa mojej pierwotnej intencji. – Paolo

Odpowiedz

5

Można zrobić:

l.extend((i for i in (2,3,4) if i not in l)) 

Rozwiązanie to nadal działa, jeśli dodana lista nie jest wyjątkowy.

+0

ten kod uzyska inny wynik, gdy numery, które mają być dołączone, nie są unikalne. takie jak: (2,3,4,4) – HYRY

+0

@ user772649: Jeśli jest taka możliwość, wystarczy rozwikłać 'set' wokół grupy liczb, które mają być dodane, rozwiąże to. – Gerrat

+0

użyj zestawu(), jeśli informacja o pozycji nie jest ważna. set() zmieni kolejność sekwencji. – HYRY

3

Odradza się używanie rozumienia list tylko dla efektów ubocznych. Nie ma nic złego w wersji 3-wierszowej.

Jeśli l robi się naprawdę długo, może chcesz zachować zestaw równolegle do unikać in l na długiej liście

7

Algorytm ten, z lub bez listy zrozumieniem, nie jest tak skuteczne, jak to możliwe; list.__contains__ to O (n), a więc dodawanie do niego elementów z innej listy to O (n). Z drugiej strony, set.__contains__ to O (log n), więc najlepszym sposobem na to jest użycie , aby użyć zestawu do sprawdzenia członkostwa oraz listy w celu zachowania porządku. W ten sposób wykonujesz n operacji O (log n), łącznie O (n log n), które są znacznie szybsze niż O (n) dla rozsądnych wartości n (powyżej powiedzmy 100 elementów) .

>>> l = [1, 2] 
>>> seen = set(l) 
>>> for x in (2, 3, 4): 
...  if x not in seen: 
...   seen.add(x) 
...   l.append(x) 
... 
>>> l 
[1, 2, 3, 4] 
>>> 
+0

+1 dla specyfikacji algorytmu – Kracekumar

3

mogę zaproponować jeszcze jedno rozwiązanie:

orig = [1,2] 
ext = [2,3,4] 
orig.extend(filter(lambda x,p=set(orig):not(x in p or p.add(x)),ext)) 

Uwzględnia elementem porządku i działa w przypadku elementów powtórzenia.

BTW, złożoność to O (n * log (n)).

+0

nadmierna sprytność, +1 mimo to. – SingleNegationElimination

Powiązane problemy