Pythonで2つのリストを比較して一致を返すにはどうすればよいですか


380

2つのリストを取り、両方に表示される値を見つけたいと思います。

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

returnMatches(a, b)

[5]たとえばを返します。


4
以下の答えはすべて私には間違っているようです。どちらかのリストで数字が繰り返されている場合はどうなるでしょうか(確かに、たとえば、両方のリストに「5」が2つあると言います)。その情報。
MH

回答:


486

最も効率的な方法ではありませんが、これを行う最も明白な方法は次のとおりです。

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

順序が重要な場合は、次のようなリスト内包表記を使用できます。

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

(同じサイズのリストでのみ機能します。これは順序の意味が意味します)。


15
注意点として、リスト内包表記必ずしも高速なオプションではありません。より大きなセット(パフォーマンスが最も重要になる可能性が高い)の場合、ビット単位の比較(&)またはset(a).intersection(b)リストの理解と同じかそれより速くなります。
Joshmaker

24
注意の別の注意:リスト内包表記は、同じ位置に両方に表示される値を検出します(これは、「順序が重要」でSilentGhostが意味したものです)。セット交差ソリューションは、異なる位置での一致も見つけます。これらは2つのまったく異なる質問への回答です...(opの質問は、それが
何を

リストがリストのリストである場合、これをどのように行うか、つまりa = [[0,0]、[1,0]]およびb = [[2,3]、[0,0]]
Schneems

3
最初の例の時間の複雑さはどうでしょうset(a) & set(b)か?
AdjunctProfessorFalcon 2017年

両方のセットが空で、比較に合格すると予想される場合、これは機能しません。「(set(a)and set(b))or(not a and not b)」に変更してください
Neil McGill

395

set.intersection()を使用すると、高速で読みやすくなります。

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

28
この回答は、アルゴリズムのパフォーマンスが良好です。リストの1つ(短いほうが望ましい)がセットになってクイックルックアップになり、他のリストがトラバースされてセット内のアイテムが検索されるためです。
u0b34a0f6ae 2009

18
bool(set(a).intersection(b))以下のためTrueFalse
Akshay

6
人々はdifferenceまたはを必要とする可能性があるため、この答えはより柔軟で読みやすくなっていunionます。
Shihe Zhang

リスト要素としてオブジェクトがあり、部分的な一致のみが必要な場合、つまり、一致するオブジェクトと見なされるには、一部の属性のみが一致する必要がある場合はどうなりますか?
CGFoX 2018年

.intersection()vsのパフォーマンスに違いはあります&か?
brandonbanks

106

Lutzのソリューションを示す簡単なパフォーマンステストが最適です。

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)

これらは私のマシンでの結果です:

# 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

言うまでもなく、人工的なパフォーマンステストは1粒ずつ行う必要set().intersection()がありますが、答えは少なくとも他のソリューションと同じくらい速く、最も読みやすいので、この一般的な問題の標準的なソリューションになるはずです。


セットは実際には繰り返しを削除しているので、私の場合は機能し
ません

@rgralmaをset既存のlistものから新規作成しても、元のものから何も削除されませんlist。リスト内の重複を処理する特別なロジックが必要な場合は、重複をどのように処理するかを具体的に回答する必要があるため、新しい質問をする必要があると思います。
Joshmaker




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
受け入れられた回答は、文字列を含むリストでは機能しません。これはします。
アントニー

12

また、一般的な要素を新しいリストに保持して、これを試すこともできます。

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

5

重複しますか?そうでない場合は、代わりにセットを使用する必要があります。


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

リストが本当に必要な場合は、java2s.com / Code / Python / List / Functiontointersecttwolists.htm >>> intersect([ 1、2、3、4、5 ]、[ 9、8、7、6、5 ])[5 ]
ティモシープラットリー2009

docによれば、...はSet( 'abc')& 'cbs'のようなエラーが発生しやすい構造を排除し、より読みやすいSet( 'abc')。intersection( 'cbs')を優先しています。- docs.python.org/library/sets.html
アーロン・ニュートン

5

リスト1(lst1)とリスト2(lst2)のリストの等価性をチェックするもう1つのもう少し機能的な方法は、オブジェクトの深さが1で、順序を保持するものです。

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 

1
このコードは質問に答えることがありますが、問題を解決する方法や理由に関する追加のコンテキストを提供すると、回答の長期的な価値が向上します。
ドナルドダック

4

itertools.productも使用できます。

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


3

以下を使用できます。

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

出力:

set([1, 7, 9])

4
これは、6年以上前に受け入れられた回答とどう違うのですか?
tmdavison

1
まあ、私は出力と完全な詳細を書き、初心者のpythonに良い
Adnan Ghaffar

2

ブール値が必要な場合:

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

次のソリューションは、リストアイテムの任意の順序で機能し、長さが異なる両方のリストをサポートしています。

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のは、そのための具体的な機能を持っていますnp.intersect1d(list1, list2)
obchardon

0

__and__属性メソッドを使用することもできます。

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

または単に

>>> 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
質問はリストのためであり、セットではありませんでした。&セットでのオペレーターの使用は、SilentGhostによる回答で既に回答されています
dWinder

0

私は次のものを使用しただけでうまくいきました:

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)

これは、あなたのケースでは5を出力します。おそらく素晴らしい賢いパフォーマンスではありません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.