Perbandingan elemen umum antara 2 daftar

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)

Sudah sejauh ini, tetapi tampaknya tidak bisa berfungsi!

Ada ide?

Daniel
sumber
1
Hai, bisakah Anda menambahkan beberapa detail tentang bagaimana Anda berencana untuk menggunakan kode? Jika ini adalah untuk menyelesaikan tugas, mungkin lebih baik untuk memilih solusi yang merangkum cara "Pythonic". Namun, jika efisiensi menjadi perhatian Anda, maka cara "Pythonic" tidak mungkin menjadi solusi yang paling efisien. Memberi tahu kami tentang perincian ini akan membantu solusi yang bertujuan menyelesaikan masalah Anda.
Matt C

Jawaban:

278
>>> list1 = [1,2,3,4,5,6]
>>> list2 = [3, 5, 7, 9]
>>> list(set(list1).intersection(list2))
[3, 5]
SilentGhost
sumber
1
+1 tetapi secara pribadi saya menggunakan frozenset karena tidak dapat diubah dan dapat digunakan sebagai kunci kamus dll
zebrabox
19
Ini akan mengembalikan elemen / unik / umum, tetapi tidak elemen berulang yang mungkin ada.
Dologan
@ SilentGhost. Cara mendapatkan jumlah elemen yang cocok dari dua daftar. Dalam hal ini adalah 2.
Poka
@Poka len (daftar (set (list1) .interseksi (list2)))
Dharmanshu Kamra
2
FYI. Ini jelas lebih cepat, daripada solusi yang diusulkan oleh Tamás, tetapi untuk kasus penggunaan yang saya lihat ketika saya berakhir di halaman ini, penting untuk menjaga urutan asli elemen untuk elemen post-filtered. Metode ini kehilangan urutan, sedangkan metode pemahaman daftar mempertahankan urutan. Penting jika ada yang perlu mempertimbangkan ini. Terima kasih.
agftrading
41

Anda juga dapat menggunakan set dan mendapatkan kesamaan dalam satu baris: kurangi set yang berisi perbedaan dari salah satu set.

A = [1,2,3,4]
B = [2,4,7,8]
commonalities = set(A) - (set(A) - set(B))
BeyondRubicon
sumber
4
Ini mengubah A menjadi dua kali, sia-sia.
wim
36

Solusi yang disarankan oleh S.Mark dan SilentGhost umumnya memberi tahu Anda bagaimana hal itu harus dilakukan dengan cara Pythonic, tetapi saya pikir Anda mungkin juga mendapat manfaat dari mengetahui mengapa solusi Anda tidak berhasil. Masalahnya adalah segera setelah Anda menemukan elemen umum pertama dalam dua daftar, Anda mengembalikan elemen tunggal saja. Solusi Anda dapat diperbaiki dengan membuat resultdaftar dan mengumpulkan elemen-elemen umum dalam daftar itu:

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

Versi yang lebih pendek menggunakan daftar pemahaman:

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

Namun, seperti yang saya katakan, ini adalah cara yang sangat tidak efisien untuk melakukan hal ini - jenis himpunan built-in Python jauh lebih efisien karena diterapkan dalam C secara internal.

Tamas
sumber
1
Cocok
1
CATATAN: Metode di atas hanya akan berfungsi untuk daftar berukuran sama. Jika Anda bekerja dengan daftar berukuran tidak sama, seperti saya, maka Anda perlu mengevaluasi urutan berdasarkan len () sebelum memanggil fungsi: list1 = [2,2,2], list2 [2,3] -> [2,2,2] list1 = [2,3], list2 [2,2,2] -> [2]
redthumb
29

gunakan set persimpangan, set (list1) & set (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']
>>>
>>>

Perhatikan bahwa daftar hasil dapat berbeda urutannya dengan daftar asli.

KAMU
sumber
Terima kasih untuk bantuannya. Pahami di mana kesalahan saya dan apa yang harus saya kerjakan di waktu berikutnya. :)
Daniel
5
solusi hebat apakah ada cara untuk menjaga ketertiban dengan ini?
tarrasch
14

Anda dapat menggunakan pemahaman daftar sederhana:

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

Set adalah cara lain kita bisa menyelesaikan ini

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

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

Saya tahu 3 cara dapat menyelesaikan ini, Tentu saja, mungkin ada lebih banyak.

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)

Cara ke-3 adalah yang tercepat karena Sets diimplementasikan menggunakan tabel hash.

Mahmoud Reda
sumber
8

Jawaban sebelumnya semuanya berfungsi untuk menemukan elemen umum yang unik, tetapi akan gagal memperhitungkan item berulang dalam daftar. Jika Anda ingin elemen umum muncul dalam jumlah yang sama seperti yang ditemukan pada daftar, Anda dapat menggunakan satu-baris berikut:

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

Bagian or Trueini hanya diperlukan jika Anda mengharapkan elemen untuk dievaluasi False.

Dologan
sumber
Solusi yang luar biasa, tampaknya yang paling menyeluruh, jika sedikit terse
Hendeca
Ini seharusnya jawaban yang seharusnya dipilih! Saya berasumsi itu juga berfungsi untuk daftar yang tidak sama. Juga sebagian besar solusi menggunakan setyang tidak stabil (alias urutannya hilang).
lifebalance
7

Saya membandingkan setiap metode yang disebutkan setiap jawaban. Saat ini saya menggunakan python 3.6.3 untuk implementasi ini. Ini adalah kode yang saya gunakan:

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)))

Jika Anda menjalankan kode ini, Anda dapat melihat bahwa jika Anda menggunakan daftar atau generator (jika Anda beralih lebih dari generator, tidak hanya menggunakannya. Saya melakukan ini ketika saya memaksa generator untuk mencetak panjangnya), Anda mendapatkan kinerja yang hampir sama. Tetapi jika Anda menggunakan set Anda mendapatkan kinerja yang jauh lebih baik. Juga jika Anda menggunakan metode persimpangan Anda akan mendapatkan kinerja yang sedikit lebih baik. hasil dari setiap metode di komputer saya tercantum di bawah ini:

  1. metode1: 0.8150673999999999974619413478649221360683441
  2. method2: 0.8329545000000001531148541289439890533685684
  3. method3: 0.0016547000000000089414697868051007390022277
  4. method4: 0.0010262999999999244948867271887138485908508
Saber Solooki
sumber
5

ini proposisi saya, saya pikir lebih mudah dengan set daripada dengan for loop

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

Kenapa tidak digunakan list comprehension ?

Solusi setengah garis:

common_elements = [x for x in list1 if x in list2]
seralouk
sumber
0

1) Method1 menyimpan list1 adalah kamus dan kemudian mengulangi setiap elem di 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)

Menemukan elemen Umum dan Berbeda:

2) Metode2 menggunakan set

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

Gunakan generator:

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

Keuntungannya di sini adalah ini akan kembali dalam waktu yang konstan (hampir instan) bahkan ketika menggunakan daftar besar atau iterables besar lainnya.

Sebagai contoh,

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

Semua jawaban lain di sini akan memakan waktu sangat lama dengan nilai-nilai ini untuk list1 dan list2.

Anda kemudian dapat mengulangi jawabannya dengan

for i in common: print(i)

Atau mengonversinya menjadi daftar dengan

list(i)
cowlinator
sumber
Ini tidak menghasilkan jawaban. Hasilnya adalah generator daripada daftar elemen umum.
josiekre
1
Benar, itu menciptakan generator, yang merupakan jawaban. Pertanyaannya adalah entah bagaimana mendapatkan elemen-elemen umum dari 2 daftar, yang mana generator ini lakukan. Cukup iterate generator seperti: for i in common: print(i). Generator adalah iterables yang sering digunakan sebagai pengganti iterables lain seperti daftar.
cowlinator