2 liste arasında ortak eleman karşılaştırması


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)

Şimdiye kadar aldım, ama işe yarayamaz gibi görünüyor!

Herhangi bir fikir?


1
Merhaba, kodu nasıl kullanmayı planladığınıza dair bazı ayrıntılar ekleyebilir misiniz? Eğer bu bir ödevi tamamlamaksa, "Pitonik" yolu kapsayan bir çözüm seçmek daha iyi olabilir. Bununla birlikte, verimlilik sizin endişenizse, "Pythonic" yolunun en verimli çözüm olması olası değildir. Bize bu ayrıntılar hakkında tavsiyelerde bulunmak, çözümlerin sorununuzu çözmeyi amaçlamasına yardımcı olacaktır.
Matt C

Yanıtlar:


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

1
+1 ama şahsen ben değişmez olduğu için frozenset kullanıyordum ve bu yüzden sözlük anahtarı vb olarak kullanılabilir
zebrabox

19
Bu, / unique / common öğelerini döndürür, ancak var olabilecek yinelenen öğeleri döndürmez.
Dologan

@SilentGhost. İki listeden eşleşen elemanların sayısı nasıl alınır. Bu durumda 2'dir.
Poka

@Poka len (list (set1) .kesit (list2)))
Dharmanshu Kamra

2
Bilginize. Bu kesinlikle Tamás tarafından önerilen çözümden daha hızlıdır, ancak bu sayfaya geldiğimde baktığım kullanım durumunda, filtrelenmiş elemanlar için elemanların orijinal sırasını korumak önemliydi. Bu yöntem sıralamayı kaybederken liste kavrama yöntemi sıralamayı korur. Herhangi birinin bunu düşünmesi gerekiyorsa önemlidir. Teşekkürler.
18'de

41

Kümeleri de kullanabilir ve ortaklıkları bir satırda alabilirsiniz: kümelerden birindeki farklılıkları içeren seti çıkarın.

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

4
Bu, A'yı gereksiz yere savurgan olmayan iki kez ayarlamaya dönüştürür.
wim

36

S.Mark ve SilentGhost tarafından önerilen çözümler genellikle bunun Pythonic olarak nasıl yapılması gerektiğini söyler, ancak çözümünüzün neden işe yaramadığını bilmekten de faydalanabileceğinizi düşündüm. Sorun, iki listedeki ilk ortak öğeyi bulduğunuzda, yalnızca bu tek öğeyi döndürmenizdir. Bir resultliste oluşturarak ve o listedeki ortak öğeleri toplayarak çözümünüz düzeltilebilir :

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

Liste kavrayışlarını kullanan daha da kısa bir sürüm:

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

Bununla birlikte, dediğim gibi, bu bunu yapmanın çok verimsiz bir yoludur - Python'un yerleşik set tipleri C'de dahili olarak uygulandıkları için çok daha etkilidir.


1
Her iki teklif için de harika
dlewin

1
NOT: Yukarıdaki yöntemler yalnızca eşit boyutlu listelerde çalışır. Eşit büyüklükteki listelerle çalışıyorsanız, benim gibi, o zaman işlevi çağırmadan önce len () 'ye göre sıralamayı değerlendirmeniz gerekir: list1 = [2,2,2], list2 [2,3] -> [2,2,2] list1 = [2,3], liste2 [2,2,2] -> [2]
redthumb

29

set kavşaklarını kullan, set (list1) ve 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']
>>>
>>>

Sonuç listesinin orijinal listeden farklı bir düzen olabileceğini unutmayın.


Yardım için teşekkürler. Nerede yanlış yaptığımı ve bir dahaki sefere ne üzerinde çalışacağımı anlayın. :)
Daniel

5
harika bir çözüm. bununla düzeni korumanın bir yolu var mı?
tarrasch

14

basit bir liste kavrayışı kullanabilirsiniz:

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

9

Set bunu çözebilmemiz için başka bir yol

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]

Bunu çözmenin 3 yolunu biliyorum, Tabii ki, daha fazlası da olabilir.

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)

3. yol en hızlı olanıdır çünkü Setler karma tablolar kullanılarak uygulanır.


8

Önceki yanıtların tümü benzersiz ortak öğeleri bulmak için çalışır, ancak listelerde tekrarlanan öğeleri hesaba katmaz. Ortak öğelerin listelerde ortak olarak bulunanlarla aynı sayıda görünmesini istiyorsanız, aşağıdaki tek astarı kullanabilirsiniz:

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

or TrueSize değerlendirmek için herhangi unsurları bekliyorsanız parçası gereklidir False.


Müthiş bir çözüm, biraz
gergin

Bu seçilmesi gereken cevap olmalı! Eşitsiz listeler için de işe yaradığını varsayıyorum. Ayrıca setkararlı olmayan çoğu çözüm kullanılır (yani sipariş kaybedilir).
ömür boyu

7

Her cevabın bahsettiği her yöntemi karşılaştırdım. Şu anda bu uygulama için python 3.6.3 kullanıyorum. Bu kullandığım kod:

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

Bu kodu çalıştırırsanız, liste veya jeneratör kullanırsanız (jeneratör üzerinde yineleme yaparsanız, sadece kullanmazsınız. Jeneratörü uzunluğunu yazdırmaya zorladığımda bunu yaptım), neredeyse aynı performansı elde edersiniz. Ancak set kullanırsanız çok daha iyi performans elde edersiniz. Ayrıca kavşak yöntemini kullanırsanız biraz daha iyi performans elde edersiniz. bilgisayarımdaki her yöntemin sonucu aşağıda listelenmiştir:

  1. yöntem1: 0.8150673999999999974619413478649221360683441
  2. yöntem2: 0.8329545000000001531148541289439890533685684
  3. method3: 0.0016547000000000089414697868051007390022277
  4. method4: 0.0010262999999999244948867271887138485908508

5

Bu benim önerim , bir döngü için olan setlerden daha kolay olduğunu düşünüyorum

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

2

Neden kullanmıyorsunuz list comprehension?

Yarım hat çözümü:

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

0

1) Yöntem1 kaydetme listesi1 sözlüktür ve daha sonra liste2'deki her elem tekrarlanır

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)

Ortak ve Farklı Unsurları Bulma:

2) set kullanarak Yöntem 2

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

-1

Bir jeneratör kullanın:

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

Buradaki avantaj, büyük listeler veya diğer büyük yinelemeler kullanıldığında bile, bunun sabit sürede (neredeyse anında) geri dönmesidir.

Örneğin,

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

Buradaki diğer tüm yanıtlar list1 ve list2 için bu değerlerle çok uzun zaman alacaktır.

Daha sonra yanıtı tekrarlayabilirsiniz.

for i in common: print(i)

Veya ile bir listeye dönüştürün

list(i)

Bu bir cevap vermez. Sonuç, ortak elemanlar listesinden ziyade bir jeneratördür.
josiekre

1
Doğru, bir cevap olan bir jeneratör yaratır. Soru, bu jeneratörün yaptığı 2 listenin ortak unsurlarını bir şekilde elde etmekti. Basitçe şöyle jeneratör yineleme: for i in common: print(i). Jeneratörler, listeler gibi diğer yinelenebilirlerin yerine sıklıkla kullanılan yinelenebilir öğelerdir.
cowlinator
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.