2つのリスト間の共通要素の比較


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)

これまでのところ、うまくいきませんでした。

何か案は?


1
こんにちは、コードをどのように使用する予定か、詳細を追加していただけますか?これが割り当てを完了することである場合、「Pythonic」の方法をカプセル化するソリューションを選択することをお勧めします。ただし、効率が懸念される場合は、「Pythonic」の方法が最も効率的なソリューションとなる可能性は低いです。これらの詳細について私たちに助言することは、ソリューションがあなたの問題を解決することを目指すのを助けるでしょう。
マットC

回答:


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

1
+1ですが、個人的には、frozensetは不変であり、辞書キーなどとして使用できるため、frozensetを使用していました
zebrabox

19
これは/ unique /共通要素を返しますが、存在する可能性のある繰り返し要素は返しません。
Dologan 2014年

@SilentGhost。2つのリストから一致する要素の数を取得する方法。このケースでは、2である
Poka

@Poka len(list(set(list1).intersection(list2)))
Dharmanshu Kamra 2018

2
ご参考までに。これは、Tamasによって提案されたソリューションよりも明らかに高速ですが、このページにたどり着いたときに見ていたユースケースでは、ポストフィルター処理された要素の元の順序を維持することが重要でした。この方法では順序が失われますが、リスト内包法では順序が保持されます。これを検討する必要がある場合は重要です。ありがとう。
2018年

41

また、セットを使用して共通性を1行で取得することもできます。違いのあるセットをセットの1つから引きます。

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

4
これにより、Aが2度セットに変換され、不必要に無駄になります。
WIM

36

S.MarkSilentGhostによって提案されたソリューションは通常、Pythonの方法でそれをどのように行う必要があるかを示しますが、ソリューションが機能しない理由を理解することにもメリットがあると思います。問題は、2つのリストで最初の共通要素が見つかるとすぐに、その単一の要素のみが返されることです。resultリストを作成し、そのリストの共通要素を収集することで、解決策を修正できます。

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

リスト内包表記を使用したさらに短いバージョン:

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

ただし、前述したように、これは非常に非効率的な方法です。Pythonの組み込みセット型は、Cで内部的に実装されているため、はるかに効率的です。


1
どちらの提案にも
最適

1
注:上記の方法は、同じサイズのリストでのみ機能します。私と同じようにサイズの異なるリストを使用している場合は、関数を呼び出す前にlen()に基づいて順序を評価する必要があります。list1 = [2,2,2]、list2 [2,3]-> [2,2,2] list1 = [2,3]、list2 [2,2,2]-> [2]
redthumb

29

セット交差、セット(リスト1)とセット(リスト2)を使用する

>>> 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']
>>>
>>>

結果リストは元のリストと異なる順序になる可能性があることに注意してください。


助けてくれてありがとう。どこで問題が発生したか、次回は何をすべきかを理解します。:)
ダニエル

5
素晴らしいソリューション。これで順序を保存する方法もありますか?
tarrasch 2012

14

単純なリスト内包表記を使用できます。

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

9

セットはこれを解決できる別の方法です

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]

これを解決するには3つの方法があります。もちろん、もっと多くの方法があります。

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番目の方法が最も高速です。


8

上記の回答はすべて、一意の共通要素を見つけるために機能しますが、リスト内の繰り返し項目を説明することはできません。共通の要素を、リストに共通して見られるのと同じ数で表示したい場合は、次のワンライナーを使用できます。

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

このor True要素は、要素がに評価されることが予想される場合にのみ必要ですFalse


少し簡潔に言えば、素晴らしい解決策が最も徹底されているようです
Hendeca

これは、選択されるべきだった答えになるはずです!等しくないリストでも機能すると想定しています。また、ほとんどのソリューションsetは安定していないものを使用します(別名、順序が失われます)。
ライフバランス2017年

7

それぞれの回答が述べている方法のそれぞれを比較しました。現時点では、この実装にpython 3.6.3を使用しています。これは私が使用したコードです:

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

このコードを実行すると、リストまたはジェネレーターを使用する場合(ジェネレーターを繰り返すだけでなく、ジェネレーターを反復処理する場合。ジェネレーターに長さを出力させたときにこれを実行しました)、ほぼ同じパフォーマンスが得られます。ただし、セットを使用すると、パフォーマンスが大幅に向上します。また、交差法を使用すると、パフォーマンスが少し向上します。私のコンピューターでの各メソッドの結果を以下に示します。

  1. 方法1:0.8150673999999999974619413478649221360683441
  2. method2:0.8329545000000001531148541289439890533685684
  3. method3:0.0016547000000000089414697868051007390022277
  4. method4:0.0010262999999999244948867271887138485908508

5

これは私の命題であり、 セットの方がforループよりも簡単だと思います

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

2

使ってみませんか list comprehensionですか?

ハーフラインソリューション:

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

0

1)Method1を保存する方法1は辞書であり、次に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)

一般的な要素と異なる要素を見つける:

2)メソッド2(セットを使用)

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

-1

ジェネレータを使用します。

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

ここでの利点は、巨大なリストやその他の巨大なイテラブルを使用している場合でも、一定の時間(ほぼ瞬時)に戻ることです。

例えば、

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

ここでの他のすべての回答は、list1とlist2のこれらの値で非常に時間がかかります。

次に、答えを繰り返すことができます

for i in common: print(i)

またはそれを使ってリストに変換します

list(i)

これは答えを出しません。結果は、一般的な要素のリストではなくジェネレータです。
josiekre

1
正解です。それは答えを生成するジェネレータを作成します。問題は、このジェネレーターが行う2つのリストの共通要素をどうにかして取得することでした。ジェネレータを次のように反復するだけですfor i in common: print(i)。ジェネレータは、リストなどの他のイテラブルの代わりに頻繁に使用されるイテラブルです。
カウリネーター
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.