So sánh các yếu tố phổ biến giữa 2 danh sách


143
def common_elements(list1, list2):
    """
    Return a list containing the elements which are in both list1 and list2

    >>> common_elements([1,2,3,4,5,6], [3,5,7,9])
    [3, 5]
    >>> common_elements(['this','this','n','that'],['this','not','that','that'])
    ['this', 'that']
    """
    for element in list1:
        if element in list2:
            return list(element)

Cho đến nay, nhưng dường như không thể làm cho nó hoạt động!

Có ý kiến ​​gì không?


1
Xin chào, bạn có thể thêm một số chi tiết về cách bạn dự định sử dụng mã không? Nếu điều này là để hoàn thành một nhiệm vụ, có thể tốt hơn là chọn một giải pháp gói gọn theo cách "Pythonic". Tuy nhiên, nếu hiệu quả là mối quan tâm của bạn, thì cách "Pythonic" dường như không phải là giải pháp hiệu quả nhất. Tư vấn cho chúng tôi về những chi tiết này sẽ giúp các giải pháp nhằm giải quyết vấn đề của bạn.
Matt C

Câu trả lời:


278
>>> list1 = [1,2,3,4,5,6]
>>> list2 = [3, 5, 7, 9]
>>> list(set(list1).intersection(list2))
[3, 5]

1
+1 nhưng cá nhân tôi đã sử dụng froundredet vì nó không thay đổi và vì vậy có thể được sử dụng làm khóa từ điển, v.v.
zebrabox

19
Điều này sẽ trả về các phần tử / unique / common, nhưng không có bất kỳ phần tử lặp lại nào có thể tồn tại.
Dologan

@SilentGhost. Làm thế nào để có được số lượng các yếu tố phù hợp từ hai danh sách. Trong trường hợp này là 2.
Poka

@Poka len (danh sách (bộ (list1) .intersection (list2)))
Dharmanshu Kamra

2
FYI. Điều này chắc chắn nhanh hơn, so với giải pháp do Tamás đề xuất, nhưng đối với trường hợp sử dụng mà tôi đã xem xét khi tôi kết thúc trang này, điều quan trọng là phải giữ nguyên thứ tự ban đầu của các phần tử cho các phần tử được lọc sau. Phương pháp này làm mất thứ tự, trong khi phương pháp hiểu danh sách bảo tồn thứ tự. Quan trọng nếu bất cứ ai cần phải xem xét điều này. Cảm ơn.
thúc

41

Bạn cũng có thể sử dụng các tập hợp và nhận các điểm tương đồng trong một dòng: trừ tập hợp có chứa các khác biệt từ một trong các tập hợp.

A = [1,2,3,4]
B = [2,4,7,8]
commonalities = set(A) - (set(A) - set(B))

4
Điều này chuyển đổi A để thiết lập hai lần, lãng phí không cần thiết.
wim

36

Các giải pháp được đề xuất bởi S.MarkSilentGhost thường cho bạn biết cách thực hiện theo cách Pythonic, nhưng tôi nghĩ bạn cũng có thể có lợi từ việc biết tại sao giải pháp của mình không hoạt động. Vấn đề là ngay khi bạn tìm thấy phần tử chung đầu tiên trong hai danh sách, bạn chỉ trả về phần tử duy nhất đó. Giải pháp của bạn có thể được khắc phục bằng cách tạo resultdanh sách và thu thập các yếu tố phổ biến trong danh sách đó:

def common_elements(list1, list2):
    result = []
    for element in list1:
        if element in list2:
            result.append(element)
    return result

Một phiên bản thậm chí ngắn hơn bằng cách sử dụng danh sách hiểu:

def common_elements(list1, list2):
    return [element for element in list1 if element in list2]

Tuy nhiên, như tôi đã nói, đây là một cách rất không hiệu quả để thực hiện điều này - các kiểu thiết lập tích hợp của Python hiệu quả hơn khi chúng được triển khai trong C bên trong.


1
Tuyệt vời cho cả hai đề xuất
dlewin

1
LƯU Ý: Các phương pháp trên sẽ chỉ hoạt động cho các danh sách có kích thước bằng nhau. Nếu bạn đang làm việc với các danh sách có kích thước không bằng nhau, như tôi, thì bạn sẽ cần đánh giá thứ tự dựa trên len () trước khi gọi hàm: list1 = [2,2,2], list2 [2,3] -> [2,2,2] list1 = [2,3], list2 [2,2,2] -> [2]
redthumb

29

sử dụng bộ giao cắt, bộ (list1) & bộ (list2)

>>> def common_elements(list1, list2):
...     return list(set(list1) & set(list2))
...
>>>
>>> common_elements([1,2,3,4,5,6], [3,5,7,9])
[3, 5]
>>>
>>> common_elements(['this','this','n','that'],['this','not','that','that'])
['this', 'that']
>>>
>>>

Lưu ý rằng danh sách kết quả có thể là thứ tự khác với danh sách ban đầu.


Cảm ơn đã giúp đỡ. Hiểu nơi tôi đã sai và những gì để làm việc vào lần tới. :)
Daniel

5
giải pháp tuyệt vời. Có cách nào để giữ gìn trật tự này không?
tarrasch

14

bạn có thể sử dụng một cách hiểu danh sách đơn giản:

x=[1,2,3,4]
y=[3,4,5]
common = [i for i in x if i in y]
common: [3,4]

9

Đặt là một cách khác chúng ta có thể giải quyết điều này

a = [3,2,4]
b = [2,3,5]
set(a)&set(b)
{2, 3}

9

list1 = [1,2,3,4,5,6] list2 = [3,5,7,9]

Tôi biết 3 cách có thể giải quyết điều này, Tất nhiên, có thể có nhiều hơn nữa.

1-

common_elements = [e for e in list1 if e in list2]

2-

import numpy as np
common_elements = np.intersect1d(list1, list2)

3-

common_elements = set(list1).intersection(list2)

Cách thứ 3 là nhanh nhất vì Bộ được triển khai bằng bảng băm.


8

Tất cả các câu trả lời trước đều hoạt động để tìm các yếu tố chung duy nhất, nhưng sẽ không tính đến các mục lặp lại trong danh sách. Nếu bạn muốn các phần tử phổ biến xuất hiện trong cùng một số như chúng được tìm thấy chung trong danh sách, bạn có thể sử dụng một trong các lớp lót sau:

l2, common = l2[:], [ e for e in l1 if e in l2 and (l2.pop(l2.index(e)) or True)]

Phần or Truenày chỉ cần thiết nếu bạn mong đợi bất kỳ yếu tố nào để đánh giá False.


Giải pháp tuyệt vời, có vẻ kỹ lưỡng nhất, nếu hơi ngắn gọn
Hendeca

Đây phải là câu trả lời nên được chọn! Tôi giả sử nó cũng hoạt động cho các danh sách không đồng đều. Ngoài ra hầu hết các giải pháp sử dụng setkhông ổn định (còn gọi là đơn hàng bị mất).
tuổi thọ

7

Tôi so sánh từng phương pháp mà mỗi câu trả lời đã đề cập. Tại thời điểm này tôi sử dụng python 3.6.3 cho việc thực hiện này. Đây là mã mà tôi đã sử dụng:

import time
import random
from decimal import Decimal


def method1():
    common_elements = [x for x in li1_temp if x in li2_temp]
     print(len(common_elements))


def method2():
    common_elements = (x for x in li1_temp if x in li2_temp)
    print(len(list(common_elements)))


def method3():
    common_elements = set(li1_temp) & set(li2_temp)
    print(len(common_elements))


def method4():
    common_elements = set(li1_temp).intersection(li2_temp)
    print(len(common_elements))


if __name__ == "__main__":
    li1 = []
    li2 = []
    for i in range(100000):
        li1.append(random.randint(0, 10000))
        li2.append(random.randint(0, 10000))

    li1_temp = list(set(li1))
    li2_temp = list(set(li2))

    methods = [method1, method2, method3, method4]
    for m in methods:
        start = time.perf_counter()
        m()
        end = time.perf_counter()
        print(Decimal((end - start)))

Nếu bạn chạy mã này, bạn có thể thấy rằng nếu bạn sử dụng danh sách hoặc trình tạo (nếu bạn lặp qua trình tạo, không chỉ sử dụng nó. Tôi đã làm điều này khi tôi buộc trình tạo để in độ dài của nó), bạn sẽ có hiệu suất gần như tương tự. Nhưng nếu bạn sử dụng thiết lập, bạn sẽ có hiệu suất tốt hơn nhiều. Ngoài ra nếu bạn sử dụng phương pháp giao nhau, bạn sẽ có hiệu suất tốt hơn một chút. kết quả của mỗi phương pháp trong máy tính của tôi được liệt kê dưới đây:

  1. phương pháp1: 0.8150673999999999974619413478649221360683441
  2. phương thức2: 0.8329545000000001531148541289439890533685684
  3. phương thức3: 0,0016547000000000089414697868051007390022277
  4. phương pháp4: 0,0010262999999999244948867271887138485908508

5

Đây là đề xuất của tôi, tôi nghĩ rằng nó dễ dàng hơn với các tập hợp hơn với một vòng lặp for

def unique_common_items(list1, list2):
   # Produce the set of *unique* common items in two lists.
   return list(set(list1) & set(list2))

2

Tại sao không sử dụng list comprehension?

Giải pháp nửa dòng:

common_elements = [x for x in list1 if x in list2]

0

1) Phương thức lưu danh sách1 là từ điển và sau đó lặp lại từng elem trong list2

def findarrayhash(a,b):
    h1={k:1 for k in a}
    for val in b:
        if val in h1:
            print("common found",val)
            del h1[val]
        else:
            print("different found",val)
    for key in h1.iterkeys():
        print ("different found",key)

Tìm các yếu tố phổ biến và khác nhau:

2) Phương thức 2 sử dụng bộ

def findarrayset(a,b):
    common = set(a)&set(b)
    diff=set(a)^set(b)
    print list(common)
    print list(diff) 

-1

Sử dụng một máy phát điện:

common = (x for x in list1 if x in list2)

Ưu điểm ở đây là điều này sẽ trở lại trong thời gian liên tục (gần như ngay lập tức) ngay cả khi sử dụng danh sách lớn hoặc các vòng lặp lớn khác.

Ví dụ,

list1 =  list(range(0,10000000))
list2=list(range(1000,20000000))
common = (x for x in list1 if x in list2)

Tất cả các câu trả lời khác ở đây sẽ mất nhiều thời gian với các giá trị này cho list1 và list2.

Sau đó, bạn có thể lặp lại câu trả lời với

for i in common: print(i)

Hoặc chuyển đổi nó thành một danh sách với

list(i)

Điều này không tạo ra một câu trả lời. Kết quả là một trình tạo chứ không phải là danh sách các yếu tố phổ biến.
josiekre

1
Chính xác, nó tạo ra một máy phát điện, đó là một câu trả lời. Câu hỏi là bằng cách nào đó có được các yếu tố phổ biến của 2 danh sách, mà trình tạo này làm. Đơn giản chỉ cần lặp lại trình tạo như vậy : for i in common: print(i). Trình tạo là các lần lặp thường được sử dụng thay cho các lần lặp khác như danh sách.
chăn bò
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.