2009-12-17 69 views
21

tôi có một danh sách với các yếu tố trùng lặp:Cách tìm các phần tử trùng lặp trong mảng bằng cách sử dụng vòng lặp trong Python?

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) 

Tôi đã sử dụng mã ở trên để tìm các yếu tố trùng lặp trong list_a. Tôi không muốn xóa các phần tử khỏi danh sách.

Nhưng tôi muốn sử dụng cho vòng lặp tại đây. Thông thường C/C++, chúng tôi sử dụng như thế này:

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] 

chúng ta sử dụng như thế nào trong Python?

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

Tôi đã thử mã trên. Nhưng nó được giải pháp sai. Tôi không biết cách tăng giá trị cho j.

Trả lời

24

Sử dụng toán tử in thay vì gọi trực tiếp __contains__.

Những gì bạn đã gần như làm việc (nhưng là 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] 

Nhưng nó dễ dàng hơn để sử dụng một bộ (khoảng O (n) do bảng băm):

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

Hoặc một dict, nếu bạn muốn theo dõi vị trí của các bản sao (còn 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 

Hoặc thậm chí chỉ cần phát hiện một bản sao ở đâu đó (còn O (n)):

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

Tại sao downvote? –

3

Nếu bạn đang tìm kiếm một-một ánh xạ giữa vòng lồng nhau của bạn và Python, đây là những gì bạn muốn:

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] 

Đoạn mã trên không phải là "Pythonic". Tôi sẽ làm điều đó một cái gì đó như thế này:

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

Ngoài ra, không sử dụng __contains__, đúng hơn, sử dụng in (như trên).

0

Bạn chỉ có thể "dịch" theo từng dòng.

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] 

Python

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++ cho vòng lặp:

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

Python tương đương:

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

Bạn không nên chấp nhận câu trả lời này. Có, đó là mã hợp lệ, nhưng nó không phải là cách bạn nên viết bằng Python. Không viết mã Python như C/C++ hoặc Java. Họ không phải là cùng một ngôn ngữ, và không có nghĩa là để được sử dụng theo cùng một cách. –

+0

Tôi đồng ý với e-satis, mặc dù câu hỏi đặc biệt cố gắng so sánh thường trình với C/C++, chúng ta nên cố gắng di chuyển nó theo đúng hướng. – Mizipzor

16

Bạn luôn có thể sử dụng một danh sách hiểu:

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

Thao tác này sẽ duyệt qua danh sách một lần cho mỗi phần tử (Mặc dù mã OP cũng là O (N ** 2), quá). –

+0

+1 cho một lớp lót – Mizipzor

+0

Vâng, tôi hiểu nó không hiệu quả. Nếu OP tìm kiếm điều đó, anh ta nên đi với câu trả lời của Roger. –

2

Sau đây đòi hỏi các yếu tố của danh sách của bạn sẽ được hashable (không chỉ thực hiện __eq__). tôi thấy nó pythonic hơn để sử dụng một defaultdict (và bạn có số lần lặp lại miễn phí):

 
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

Thay đổi thành 'if d [v]> 1' và tôi sẽ +1. –

+0

Chris: Tôi nghĩ bạn đã hiểu sai câu trả lời này, nó hoạt động như bây giờ và đề xuất của bạn sẽ phá vỡ nó. –

56

Chỉ cần cung cấp thông tin, Trong python 2.7+, chúng ta có thể sử dụng 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 danh sách

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

Items tìm thấy hơn 1 lần

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

Items tìm thấy chỉ có một thời gian

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

+1, chắc chắn là pythonic. – LeMiz

+2

'[n cho n, i trong y.iteritems() nếu i> 1]' thay vào đó, và 'i == 1'. –

+0

... nhưng tại sao danh sách (y), không phải là Counter có thể lặp lại? – LeMiz

-2

thực hiện Pythonic hơn một chút (không phải là nhất, tất nhiên), nhưng theo tinh thần của mã C của bạn có thể là:

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

Sửa : có, nó in các phần tử nhiều hơn một lần nếu có nhiều hơn 2 lần lặp lại, nhưng đó là những gì mã C giả của op cũng vậy.

+0

Bạn phải sắp xếp trước khi thực hiện điều đó. Sử dụng được sắp xếp.Hơn nữa, bạn sẽ in cùng một bản sao nhiều lần nếu có nhiều hơn một lần giống nhau. –

+0

Điều này sẽ in cùng một phần tử nhiều lần nếu nó xuất hiện nhiều hơn 2 lần trong danh sách. – truppo

+1

Các bạn có bận tâm đọc mã của op không? Nó thực hiện chính xác như nhau. @ e-satis Không cần phải sắp xếp, có thể bạn có nghĩa là một cái gì đó như '[k cho k, nó trong itertools.groupby (sắp xếp (l)) nếu len (danh sách (it))> 1]'? – fortran

7

Trước Python 2.3, sử dụng 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 

Vì vậy, một chức năng:

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) 

Với Python 2.3 đi kèm set(), và nó thậm chí còn một built-in sau hơn:

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 

Với Python 2.7 trở lên, bạn có collections mô-đun cung cấp ng các chức năng rất giống nhau hơn so với dict một, và chúng ta có thể làm cho nó ngắn hơn (và nhanh hơn, nó có thể là C dưới mui xe) so với giải pháp 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) 

Tôi muốn gắn bó với giải pháp 2.

0

Sử dụng 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

Dường như bạn có một danh sách (list_a) có khả năng bao gồm bản sao, mà bạn muốn giữ như nó có, và xây dựng một de-sao chép danh sách tmp dựa trên list_a. Trong Python 2.7, bạn có thể thực hiện điều này với một dòng:

tmp = list(set(list_a))

So sánh độ dài của tmplist_a vào thời điểm này nên làm rõ nếu có được thực sự lặp lại các mục trong list_a. Điều này có thể giúp đơn giản hóa mọi thứ nếu bạn muốn đi vào vòng lặp để xử lý bổ sung.

0

Chỉ cần nhanh chóng và dơ bẩn,

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 

Output [1, 2, 3, 5, 6, 7]

2

Chỉ sử dụng itertools, và hoạt động tốt trên Python 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)]) 

Kết quả:

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

Trong trường hợp Py thon3 và nếu bạn hai danh sách

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

Cấp, tôi đã không thực hiện bài kiểm tra, nhưng tôi đoán nó sẽ được khó khăn để đánh bại gấu trúc ở tốc độ:

pd.DataFrame(list_a, columns=["x"]).groupby('x').size().to_dict() 
Các vấn đề liên quan