Python ve dönüş eşleşmelerinde iki listeyi nasıl karşılaştırabilirim?


380

İki liste alıp her ikisinde de görünen değerleri bulmak istiyorum.

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

returnMatches(a, b)

[5]mesela geri dönecekti .


4
Aşağıdaki cevaplar bana yanlış geliyor. Her iki listede de bir sayı tekrarlanırsa, ne olacağını bilmek istersiniz (?) bu bilgi.
MH

Yanıtlar:


486

En verimli olanı değil, ama bunu yapmanın en belirgin yolu:

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

sipariş önemliyse, bunu aşağıdaki liste kavrayışlarıyla yapabilirsiniz:

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

(yalnızca sipariş öneminin ima ettiği eşit boyutlu listeler için geçerlidir).


15
Uyarı notu, liste anlama olduğunu değil mutlaka daha hızlı bir seçenek. Daha büyük kümeler için (performansın önemli olduğu yerler) bitsel karşılaştırma ( &) veya set(a).intersection(b)liste kavramadan daha hızlı veya daha hızlı olacaktır.
Joshmaker

24
Dikkat edilmesi gereken başka bir not: liste kavrama işlemi, SAME konumlarının her ikisinde de görünen değerleri bulur (SilentGhost'un "sıra önemlidir" ile kastedilen). Ayarlanan kavşak çözümleri ayrıca FARKLI konumlarda eşleşmeler de bulacaktır. Bunlar 2 farklı soruya cevaplar ... (
op'un

Listeleriniz listelerin listesiyse bunu nasıl yaparsınız; örneğin a = [[0,0], [1,0]] ve b = [[2,3], [0,0]]
Schneems

3
İlk örneğin zaman karmaşıklığı ne olurdu set(a) & set(b)?
AdjunctProfessorFalcon

Her iki küme de boşsa ve karşılaştırmanın geçmesini beklerseniz, bu çalışmaz. Bu yüzden "(set (a) ve set (b)) veya (a değil b değil)" olarak değiştirin
Neil McGill

395

Set.intersection () kullanın , hızlı ve okunabilir.

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

28
Bu cevap iyi bir algoritmik performansa sahiptir, çünkü listelerden sadece biri (daha kısa tercih edilmelidir) hızlı arama için bir kümeye dönüştürülür ve diğer liste kümedeki öğelerini ararken dolaşılır.
u0b34a0f6ae

18
bool(set(a).intersection(b))için Trueya daFalse
Akshay

6
Bu cevap daha esnek ve okunabilir, çünkü insanların ihtiyacı olabilir differenceveya union.
Shihe Zhang

Liste öğeleri olarak nesnelerim varsa ve yalnızca kısmi eşleşmeler istiyorsanız, yani eşleşen nesneler olarak değerlendirilebilmesi için yalnızca bazı özniteliklerin eşleşmesi gerekir?
CGFoX

.intersection()Vs için herhangi bir performans farkı var mı &?
brandonbanks

106

Lutz'in çözümünü gösteren hızlı performans testi en iyisidir:

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)

Bunlar makinemdeki sonuçlar:

# 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

Açıkçası, herhangi bir yapay performans testi bir tuz tanesi ile alınmalıdır, ancak set().intersection()cevap en azından diğer çözümler kadar hızlı ve aynı zamanda en okunabilir olduğundan, bu yaygın sorun için standart çözüm olmalıdır.


Set aslında tekrarları kaldırıyor, bu yüzden benim durumumda işe yaramaz
rgralma

@rgralma setmevcut olandan yeni bir listşey yapmak orijinalden hiçbir şeyi kaldırmaz list. Özel mantığın bir liste içindeki kopyaları işlemesini istiyorsanız, yeni bir soru sormanız gerektiğini düşünüyorum çünkü cevabın kopyaların nasıl ele alınmasını istediğinize özgü olması gerekir.
Joshmaker


15

Bunu yapmanın en kolay yolu setleri kullanmaktır :

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


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
Kabul edilen cevap, dize içeren listelerde çalışmaz. Bunu yapar.
Antony

12

Ayrıca, ortak öğeleri yeni bir listede tutarak bunu deneyebilirsiniz.

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

5

Kopyalar istiyor musunuz? Değilse, bunun yerine setleri kullanmalısınız:


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

Gerçekten listeler istiyorsanız, java2s.com/Code/Python/List/Functiontointersecttwolists.htm >>> kesişim ([1, 2, 3, 4, 5], [9, 8, 7, 6, 5]) [5 ]
Timothy Pratley

Doc'a göre - ... daha okunabilir Set ('abc'). Kesişme ('cbs') lehine Set ('abc') & 'cbs' gibi hataya açık yapıları engeller. - docs.python.org/library/sets.html
Aaron Newton

5

nesnelerin bir derinliğe sahip olduğu ve sırasını koruyan liste 1 (lst1) ve liste 2 (lst2) için liste eşitliğini kontrol etmenin biraz daha işlevsel bir yolu:

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 

Bu kod soruyu cevaplayabilirken, sorunun nasıl ve / veya neden çözüldüğüne dair ek bağlam sağlamak yanıtlayıcının uzun vadeli değerini artıracaktır.
Donald Duck

4

İtertools.product da kullanabilirsiniz.

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

3

Kullanabilirsiniz

def returnMatches(a,b):
       return list(set(a) & set(b))

3

Kullanabilirsiniz:

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

Çıktı:

set([1, 7, 9])

4
bu 6+ yıl önceki kabul edilen cevaptan nasıl farklı?
tmdavison

1
Tamamen çıktı ile detay ve yeni başlayan python için iyi yazdım
Adnan Ghaffar

2

Bir boolean değeri istiyorsanız:

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

Aşağıdaki çözüm, liste öğelerinin herhangi bir sırası için çalışır ve her iki listenin de farklı uzunluklarda olmasını destekler.

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 bunun için belirli bir işleve sahiptir:np.intersect1d(list1, list2)
obchardon

0

__and__Öznitelik yöntemini kullanarak da çalışır.

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

ya da sadece

>>> 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
Soru liste içindi ve ayarlanmadı. &sette operatörün kullanımı zaten kabul edilen cevapta SilentGhost tarafından cevaplandı
dWinder

0

Sadece aşağıdakileri kullandım ve benim için çalıştı:

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)

bu durumda 5 yazdı. Muhtemelen büyük performans akıllıca olsa.

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.