Làm thế nào tôi có thể so sánh hai danh sách trong python và trả lại trận đấu


380

Tôi muốn lấy hai danh sách và tìm các giá trị xuất hiện trong cả hai.

a = [1, 2, 3, 4, 5]
b = [9, 8, 7, 6, 5]

returnMatches(a, b)

sẽ trở lại [5], ví dụ.


4
Các câu trả lời dưới đây dường như sai với tôi. Điều gì xảy ra nếu một số được lặp lại trong một trong hai danh sách, chắc chắn bạn muốn biết rằng (?) (Ví dụ: nói cả hai danh sách có '5' hai lần) Bất kỳ giải pháp nào sử dụng bộ sẽ xóa ngay lập tức tất cả các mục lặp lại và bạn sẽ mất thông tin đó
MH

Câu trả lời:


486

Không phải là cách hiệu quả nhất, nhưng cho đến nay, cách rõ ràng nhất để làm điều đó là:

>>> a = [1, 2, 3, 4, 5]
>>> b = [9, 8, 7, 6, 5]
>>> set(a) & set(b)
{5}

Nếu thứ tự là quan trọng, bạn có thể làm điều đó với việc hiểu danh sách như thế này:

>>> [i for i, j in zip(a, b) if i == j]
[5]

(chỉ hoạt động cho các danh sách có kích thước bằng nhau, có ý nghĩa theo thứ tự).


15
Một lưu ý thận trọng, việc hiểu danh sách không nhất thiết là lựa chọn nhanh hơn. Đối với các tập lớn hơn (trong đó hiệu suất có khả năng quan trọng nhất), so sánh bitwise ( &) hoặc set(a).intersection(b)sẽ nhanh hoặc nhanh hơn so với hiểu danh sách.
Joshmaker

24
Một lưu ý khác: sự hiểu biết danh sách tìm thấy các giá trị xuất hiện ở cả hai vị trí CÙNG (đây là ý nghĩa của SilentGhost bởi "thứ tự là quan trọng"). Các giải pháp giao cắt được thiết lập cũng sẽ tìm thấy kết quả khớp tại các vị trí KHÁC BIỆT. Đây là những câu trả lời cho 2 câu hỏi khá khác nhau ... (câu hỏi của op không rõ ràng về câu hỏi đó)
drevicko

Làm thế nào để bạn làm điều này nếu danh sách của bạn là danh sách các danh sách tức là a = [[0,0], [1,0]] và b = [[2,3], [0,0]]
Schneems

3
Điều gì sẽ là phức tạp thời gian của ví dụ đầu tiên set(a) & set(b)?
AdjuncProfigatorFalcon

Lưu ý, điều này không hoạt động nếu cả hai bộ đều trống và bạn mong muốn so sánh sẽ vượt qua. Vì vậy, thay đổi thành "(đặt (a) và đặt (b)) hoặc (không phải a và không b)"
Neil McGill

395

Sử dụng set.intersection () , nó nhanh và dễ đọc.

>>> set(a).intersection(b)
set([5])

28
Câu trả lời này có hiệu suất thuật toán tốt, vì chỉ một trong các danh sách (nên được ưu tiên ngắn hơn) được chuyển thành một bộ để tra cứu nhanh và danh sách khác được tra cứu tìm các mục của nó trong tập hợp.
u0b34a0f6ae

18
bool(set(a).intersection(b))cho TruehoặcFalse
Akshay

6
Câu trả lời này linh hoạt hơn và dễ đọc hơn, vì mọi người có thể cần differencehoặc union.
Shihe Zhang

Điều gì sẽ xảy ra nếu tôi có các đối tượng làm thành phần danh sách và chỉ muốn khớp một phần, tức là chỉ một số thuộc tính phải khớp với nó để được coi là đối tượng phù hợp?
CGFoX

Có sự khác biệt hiệu suất cho .intersection()vs &?
brandonbanks

106

Một thử nghiệm hiệu suất nhanh cho thấy giải pháp của Lutz là tốt nhất:

import time

def speed_test(func):
    def wrapper(*args, **kwargs):
        t1 = time.time()
        for x in xrange(5000):
            results = func(*args, **kwargs)
        t2 = time.time()
        print '%s took %0.3f ms' % (func.func_name, (t2-t1)*1000.0)
        return results
    return wrapper

@speed_test
def compare_bitwise(x, y):
    set_x = frozenset(x)
    set_y = frozenset(y)
    return set_x & set_y

@speed_test
def compare_listcomp(x, y):
    return [i for i, j in zip(x, y) if i == j]

@speed_test
def compare_intersect(x, y):
    return frozenset(x).intersection(y)

# Comparing short lists
a = [1, 2, 3, 4, 5]
b = [9, 8, 7, 6, 5]
compare_bitwise(a, b)
compare_listcomp(a, b)
compare_intersect(a, b)

# Comparing longer lists
import random
a = random.sample(xrange(100000), 10000)
b = random.sample(xrange(100000), 10000)
compare_bitwise(a, b)
compare_listcomp(a, b)
compare_intersect(a, b)

Đây là kết quả trên máy của tôi:

# Short list:
compare_bitwise took 10.145 ms
compare_listcomp took 11.157 ms
compare_intersect took 7.461 ms

# Long list:
compare_bitwise took 11203.709 ms
compare_listcomp took 17361.736 ms
compare_intersect took 6833.768 ms

Rõ ràng, bất kỳ thử nghiệm hiệu suất nhân tạo nào cũng nên được thực hiện bằng một hạt muối, nhưng vì set().intersection()câu trả lời ít nhất là nhanh như các giải pháp khác, và cũng dễ đọc nhất, nên nó là giải pháp chuẩn cho vấn đề phổ biến này.


Set thực sự đang loại bỏ sự lặp lại, vì vậy trong trường hợp của tôi sẽ không hoạt động
rgralma

@rgralma tạo một cái mới settừ một cái hiện có listsẽ không xóa bất cứ thứ gì khỏi bản gốc list. Nếu bạn muốn logic đặc biệt để xử lý các bản sao trong danh sách, tôi nghĩ bạn sẽ cần hỏi một câu hỏi mới vì câu trả lời sẽ cần phải cụ thể theo cách bạn muốn xử lý các bản sao.
Joshmaker

67

Tôi thích các câu trả lời dựa trên tập hợp, nhưng đây là câu trả lời hoạt động

[x for x in a if x in b]

15

Cách dễ nhất để làm điều đó là sử dụng các bộ :

>>> a = [1, 2, 3, 4, 5]
>>> b = [9, 8, 7, 6, 5]
>>> set(a) & set(b)
set([5])


14
>>> s = ['a','b','c']   
>>> f = ['a','b','d','c']  
>>> ss= set(s)  
>>> fs =set(f)  
>>> print ss.intersection(fs)   
   **set(['a', 'c', 'b'])**  
>>> print ss.union(fs)        
   **set(['a', 'c', 'b', 'd'])**  
>>> print ss.union(fs)  - ss.intersection(fs)   
   **set(['d'])**

1
Câu trả lời được chấp nhận không hoạt động đối với các danh sách có chứa chuỗi. Cái này nào.
Antony

12

Ngoài ra, bạn có thể thử điều này, bằng cách giữ các yếu tố phổ biến trong một danh sách mới.

new_list = []
for element in a:
    if element in b:
        new_list.append(element)

5

Bạn có muốn trùng lặp? Nếu không có lẽ bạn nên sử dụng bộ thay thế:


>>> set([1, 2, 3, 4, 5]).intersection(set([9, 8, 7, 6, 5]))
set([5])

Nếu bạn thực sự muốn có danh sách, java2s.com/Code/Python/List/Funciontointersecttwolists.htmlm >>> giao nhau ([1, 2, 3, 4, 5], [9, 8, 7, 6, 5]) [5 ]
Timothy Pratley

Theo tài liệu - ... loại trừ các cấu trúc dễ bị lỗi như Set ('abc') & 'cbs' có lợi cho Set dễ đọc hơn ('abc'). Giao điểm ('cbs'). - docs.python.org/l Library / sets.html
Aaron Newton

5

một cách khác có chức năng hơn một chút để kiểm tra sự bình đẳng danh sách cho danh sách 1 (lst1) và danh sách 2 (lst2) trong đó các đối tượng có độ sâu một và giữ trật tự là:

all(i == j for i, j in zip(lst1, lst2))   

4
a = [1, 2, 3, 4, 5]
b = [9, 8, 7, 6, 5]

lista =set(a)
listb =set(b)   
print listb.intersection(lista)   
returnMatches = set(['5']) #output 

print " ".join(str(return) for return in returnMatches ) # remove the set()   

 5        #final output 

Mặc dù mã này có thể trả lời câu hỏi, việc cung cấp ngữ cảnh bổ sung về cách thức và / hoặc lý do giải quyết vấn đề sẽ cải thiện giá trị lâu dài của câu trả lời.
Vịt Donald

4

Có thể sử dụng itertools.product quá.

>>> common_elements=[]
>>> for i in list(itertools.product(a,b)):
...     if i[0] == i[1]:
...         common_elements.append(i[0])

3

Bạn có thể dùng

def returnMatches(a,b):
       return list(set(a) & set(b))

3

Bạn có thể dùng:

a = [1, 3, 4, 5, 9, 6, 7, 8]
b = [1, 7, 0, 9]
same_values = set(a) & set(b)
print same_values

Đầu ra:

set([1, 7, 9])

4
Điều này khác với câu trả lời được chấp nhận từ hơn 6 năm trước như thế nào?
tmdavison

1
Chà, tôi đã viết chi tiết đầy đủ với đầu ra và tốt cho con trăn mới bắt đầu
Adnan Ghaffar

2

Nếu bạn muốn một giá trị boolean:

>>> a = [1, 2, 3, 4, 5]
>>> b = [9, 8, 7, 6, 5]
>>> set(b) == set(a)  & set(b) and set(a) == set(a) & set(b)
False
>>> a = [3,1,2]
>>> b = [1,2,3]
>>> set(b) == set(a)  & set(b) and set(a) == set(a) & set(b)
True

1

Giải pháp sau đây hoạt động cho mọi thứ tự của danh sách và cũng hỗ trợ cả hai danh sách có độ dài khác nhau.

import numpy as np
def getMatches(a, b):
    matches = []
    unique_a = np.unique(a)
    unique_b = np.unique(b)
    for a in unique_a:
        for b in unique_b:
            if a == b:
                matches.append(a)
    return matches
print(getMatches([1, 2, 3, 4, 5], [9, 8, 7, 6, 5, 9])) # displays [5]
print(getMatches([1, 2, 3], [3, 4, 5, 1])) # displays [1, 3]

1
Numpy có một chức năng cụ thể cho điều đó:np.intersect1d(list1, list2)
obchardon

0

Sử dụng __and__phương pháp thuộc tính cũng hoạt động.

>>> a = [1, 2, 3, 4, 5]
>>> b = [9, 8, 7, 6, 5]
>>> set(a).__and__(set(b))
set([5])

hoặc đơn giản

>>> set([1, 2, 3, 4, 5]).__and__(set([9, 8, 7, 6, 5]))
set([5])
>>>    

0
you can | for set union and & for set intersection.
for example:

    set1={1,2,3}
    set2={3,4,5}
    print(set1&set2)
    output=3

    set1={1,2,3}
    set2={3,4,5}
    print(set1|set2)
    output=1,2,3,4,5

curly braces in the answer.

4
Câu hỏi là cho danh sách và không có bộ. việc sử dụng &toán tử trên tập đã được SilentGhost trả lời trong câu trả lời được chấp nhận
dWinder 18/07/18

0

Tôi chỉ sử dụng như sau và nó làm việc cho tôi:

group1 = [1, 2, 3, 4, 5]
group2 = [9, 8, 7, 6, 5]

for k in group1:
    for v in group2:
        if k == v:
            print(k)

Điều này sau đó sẽ in 5 trong trường hợp của bạn. Có lẽ không phải là hiệu suất tuyệt vời khôn ngoan mặc dù.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.