2009-12-17 12 views
21

Mam listę ze zduplikowanych elementów:Jak znaleźć duplikaty elementów w tablicy przy użyciu pętli for w Pythonie?

list_a=[1,2,3,5,6,7,5,2] 

tmp=[] 

for i in list_a: 
    if tmp.__contains__(i): 
     print i 
    else: 
     tmp.append(i) 

Użyłem powyższy kod, aby znaleźć zduplikowane elementy w list_a. Nie chcę usuwać elementów z listy.

Ale chcę tutaj użyć pętli. Normalnie C/C++ używamy tak Chyba:

for (int i=0;i<=list_a.length;i++) 
    for (int j=i+1;j<=list_a.length;j++) 
     if (list_a[i]==list_a[j]) 
      print list_a[i] 

jak używamy jak to w Pythonie?

for i in list_a: 
    for j in list_a[1:]: 
    .... 

Próbowałem powyższego kodu. Ale rozwiązanie jest złe. Nie wiem, jak zwiększyć wartość dla j.

Odpowiedz

24

Użyj operatora in zamiast dzwonić bezpośrednio pod numer __contains__.

Co masz prawie działa (ale jest O (n ** 2)):

for i in xrange(len(list_a)): 
    for j in xrange(i + 1, len(list_a)): 
    if list_a[i] == list_a[j]: 
     print "duplicate:", list_a[i] 

ale jest to o wiele łatwiejsze w użyciu zestaw (w przybliżeniu O (n) ze względu na tablicy mieszającej):

seen = set() 
for n in list_a: 
    if n in seen: 
    print "duplicate:", n 
    else: 
    seen.add(n) 

Albo DICT, jeśli chcesz śledzić lokalizacje również duplikatów (o (n)):

import collections 
items = collections.defaultdict(list) 
for i, item in enumerate(list_a): 
    items[item].append(i) 
for item, locs in items.iteritems(): 
    if len(locs) > 1: 
    print "duplicates of", item, "at", locs 

lub nawet tylko wykryje duplikat gdzieś (także o (n)):

if len(set(list_a)) != len(list_a): 
    print "duplicate" 
+0

Dlaczego downvote? –

3

Jeśli szukasz jeden do jednego mapowania między swoimi zagnieżdżonych pętli i Pythonie, to jest to, co chcesz:

n = len(list_a) 
for i in range(n): 
    for j in range(i+1, n): 
     if list_a[i] == list_a[j]: 
      print list_a[i] 

Powyższy kod nie jest „pythonowy”. Chciałbym zrobić to tak:

seen = set() 
for i in list_a: 
    if i in seen: 
     print i 
    else: 
     seen.add(i) 

Nie należy również używać __contains__ raczej używać in (jak wyżej).

0

Można po prostu "przetłumaczyć" wiersz po linii.

C++

for (int i=0;i<=list_a.length;i++) 
    for (int j=i+1;j<=list_a.length;j++) 
     if (list_a[i]==list_a[j]) 
      print list_a[i] 

Pythona

for i in range(0, len(list_a)): 
    for j in range(i + 1, len(list_a)) 
     if list_a[i] == list_a[j]: 
      print list_a[i] 

C++ w pętli:

for(int x = start; x < end; ++x) 

Pythona równoważne:

for x in range(start, end): 
+3

Nie należy akceptować tej odpowiedzi. Tak, to jest poprawny kod, ale nie jest to sposób, w jaki powinieneś kodować w Pythonie. Nie koduj Pythona takiego jak C/C++ lub Java. Nie są to te same języki i nie należy ich używać w ten sam sposób. –

+0

Zgadzam się z e-satis, chociaż pytanie w szczególności próbuje porównać rutynę z C/C++, powinniśmy spróbować przesunąć to we właściwym kierunku. – Mizipzor

16

Zawsze możesz użyć wyrażeń listowych:

dups = [x for x in list_a if list_a.count(x) > 1] 
+3

Powoduje to wyświetlenie listy raz dla każdego elementu (chociaż kod OP to również O (N ** 2)). –

+0

+1 dla jednego liniowca – Mizipzor

+0

Tak, zrozumiałem, że to nieefektywne. Jeśli PO tego szuka, powinien na pewno odpowiedzieć na pytania Rogera. –

2

Poniższa wymaga elementów listy za hashable (nie tylko wykonawczy __eq__). Uważam to bardziej pythonic użyć defaultdict (i masz liczbę powtórzeń za darmo):

 
import collections 
l = [1, 2, 4, 1, 3, 3] 
d = collections.defaultdict(int) 
for x in l: 
    d[x] += 1 
print [k for k, v in d.iteritems() if v > 1] 
# prints [1, 3] 
+0

Zmień na 'if d [v]> 1', a otrzymam +1. –

+0

Chris: Wydaje mi się, że źle zrozumiałeś tę odpowiedź, działa tak, jak jest teraz, a twoja sugestia ją zepsuje. –

56

Tylko dla informacji, w python 2.7+, możemy użyć Counter

import collections 

x=[1, 2, 3, 5, 6, 7, 5, 2] 

>>> x 
[1, 2, 3, 5, 6, 7, 5, 2] 

>>> y=collections.Counter(x) 
>>> y 
Counter({2: 2, 5: 2, 1: 1, 3: 1, 6: 1, 7: 1}) 

Unique Lista

>>> list(y) 
[1, 2, 3, 5, 6, 7] 

znalezione więcej niż 1 raz

>>> [i for i in y if y[i]>1] 
[2, 5] 

Znalezione tylko raz

>>> [i for i in y if y[i]==1] 
[1, 3, 6, 7] 
+0

+1, zdecydowanie pythonic. – LeMiz

+2

'[n dla n, i w y.iteritems(), jeśli i> 1]' zamiast, i 'i == 1'. –

+0

... ale dlaczego lista (y) nie jest Counter iterable? – LeMiz

-2

Trochę więcej pythonowy realizacja (nie najbardziej, oczywiście), ale w duchu kodzie C mogą być:

for i, elem in enumerate(seq): 
    if elem in seq[i+1:]: 
     print elem 

Edycja : tak, wypisuje elementy więcej niż jeden raz, jeśli występują więcej niż 2 powtórzenia, ale tak samo działa pseudo kod C operacji.

+0

Musisz sortować przed zrobieniem tego. Użyj posortowane.Co więcej, wydrukujesz ten sam duplikat kilka razy, jeśli jest ich więcej. –

+0

Spowoduje to wydrukowanie tego samego elementu wiele razy, jeśli wystąpi więcej niż 2 razy na liście. – truppo

+1

Czy chcieliście przeczytać kod op? Robi dokładnie to samo. @ e-satis Nie ma potrzeby sortowania, może miałeś na myśli coś w rodzaju '[k dla k, to w itertools.groupby (posortowane (l)) jeśli len (list (it))> 1]'? – fortran

7

Przed Pythonie 2.3, wykorzystanie dict():

>>> lst = [1, 2, 3, 5, 6, 7, 5, 2] 
>>> stats = {} 
>>> for x in lst : # count occurrences of each letter: 
...  stats[x] = stats.get(x, 0) + 1 
>>> print stats 
{1: 1, 2: 2, 3: 1, 5: 2, 6: 1, 7: 1} # filter letters appearing more than once: 
>>> duplicates = [dup for (dup, i) in stats.items() if i > 1] 
>>> print duplicates 

Więc funkcja:

def getDuplicates(iterable): 
    """ 
     Take an iterable and return a generator yielding its duplicate items. 
     Items must be hashable. 

     e.g : 

     >>> sorted(list(getDuplicates([1, 2, 3, 5, 6, 7, 5, 2]))) 
     [2, 5] 
    """ 
    stats = {} 
    for x in iterable : 
     stats[x] = stats.get(x, 0) + 1 
    return (dup for (dup, i) in stats.items() if i > 1) 

z Pythonem 2.3 pochodzi set(), i to nawet wbudowany po niż:

def getDuplicates(iterable): 
    """ 
     Take an iterable and return a generator yielding its duplicate items. 
     Items must be hashable. 

     e.g : 

     >>> sorted(list(getDuplicates([1, 2, 3, 5, 6, 7, 5, 2]))) 
     [2, 5] 
    """ 
    try: # try using built-in set 
     found = set() 
    except NameError: # fallback on the sets module 
     from sets import Set 
     found = Set() 

    for x in iterable: 
     if x in found : # set is a collection that can't contain duplicate 
      yield x 
     found.add(x) # duplicate won't be added anyway 

z Pythonem 2.7 i wyżej, masz providi collections modułu ng tę samą funkcję niż dict jeden, i możemy zrobić to krótszy (i szybciej, to prawdopodobnie pod maską C) niż w roztworze 1:

import collections 

def getDuplicates(iterable): 
    """ 
     Take an iterable and return a generator yielding its duplicate items. 
     Items must be hashable. 

     e.g : 

     >>> sorted(list(getDuplicates([1, 2, 3, 5, 6, 7, 5, 2]))) 
     [2, 5] 
    """ 
    return (dup for (dup, i) in collections.counter(iterable).items() if i > 1) 

będę trzymać roztworem 2.

0

Korzystanie numpy:

import numpy as np 
count,value = np.histogram(list_a,bins=np.hstack((np.unique(list_a),np.inf))) 
print 'duplicate value(s) in list_a: ' + ', '.join([str(v) for v in value[count>1]]) 
5
def get_duplicates(arr): 
    dup_arr = arr[:] 
    for i in set(arr): 
     dup_arr.remove(i)  
    return list(set(dup_arr)) 


print get_duplicates([1,2,3,5,6,7,5,2]) 
[2, 5] 

print get_duplicates([1,2,1,3,4,5,4,4,6,7,8,2]) 
[1, 2, 4] 
1

Wygląda na to, że masz listę (list_a) potencjalnie tym duplikatów, które wolisz zachować jak to jest, i zbudować deduplikowane listy tmp oparciu o list_a. W Pythonie 2.7, można to osiągnąć z jednej linii:

tmp = list(set(list_a))

Porównując długości tmp i list_a w tym miejscu należy wyjaśnić, jeśli nie zostały faktycznie powielać elementów w list_a. Może to uprościć sytuację, jeśli chcesz przejść do pętli w celu dodatkowego przetwarzania.

0

tylko szybkie i brudnych,

list_a=[1,2,3,5,6,7,5,2] 
holding_list=[] 

for x in list_a: 
    if x in holding_list: 
     pass 
    else: 
     holding_list.append(x) 

print holding_list 

wyjściowy [1, 2, 3, 5, 6, 7]

2

użyciu jedynie itertools i współpracuje Pythona 2,5

from itertools import groupby 
list_a = sorted([1, 2, 3, 5, 6, 7, 5, 2]) 
result = dict([(r, len(list(grp))) for r, grp in groupby(list_a)]) 

Wynik:

{1: 1, 2: 2, 3: 1, 5: 2, 6: 1, 7: 1} 
0

W przypadku Py thon3 a jeśli dwie listy

def removedup(List1,List2): 
    List1_copy = List1[:] 
     for i in List1_copy: 
      if i in List2: 
       List1.remove(i) 

List1 = [4,5,6,7] 
List2 = [6,7,8,9] 
removedup(List1,List2) 
print (List1) 
0

prawda, ja nie wykonano testów, ale myślę, że będzie trudno pokonać pandy prędkości:

pd.DataFrame(list_a, columns=["x"]).groupby('x').size().to_dict() 
Powiązane problemy