Comment trouver l'intersection de liste?

204
a = [1,2,3,4,5]
b = [1,3,5,6]
c = a and b
print c

sortie réelle: [1,3,5,6] sortie attendue:[1,3,5]

Comment réaliser une opération booléenne ET (intersection de listes) sur deux listes?

csguy11
la source
6
Le problème ici est que cela a and bfonctionne comme l' instruction suivante de la documentation le mentionne: " L'expression est d' x and yabord évaluée x; si elle xest fausse, sa valeur est renvoyée; sinon, elle yest évaluée et la valeur résultante est renvoyée. "
Tadeck

Réponses:

350

Si l'ordre n'est pas important et que vous n'avez pas à vous soucier des doublons, vous pouvez utiliser l'intersection définie:

>>> a = [1,2,3,4,5]
>>> b = [1,3,5,6]
>>> list(set(a) & set(b))
[1, 3, 5]
Mark Byers
la source
9
que se passe-t-il si a = [1,1,2,3,4,5]et b = [1,1,3,5,6]ensuite l'intersection est, [1,1,3,5]mais par la méthode ci-dessus, il n'en résultera qu'une seule, 1c'est-à-dire [1, 3, 5]quelle sera la façon d'écrire pour le faire alors?
Nitish Kumar Pal
6
@NItishKumarPal intersectionest généralement compris comme étant basé sur un ensemble . Vous recherchez un animal légèrement différent - et vous devrez peut-être le faire manuellement en triant chaque liste et en fusionnant les résultats - et en gardant des doublons dans la fusion.
javadba
1
@MarkByers Cela n'aura pas de doublons.
javadba
85

Utiliser des listes de compréhension est assez évident pour moi. Je ne suis pas sûr de la performance, mais au moins les choses restent des listes.

[x for x in a if x in b]

Ou "toutes les valeurs x qui sont dans A, si la valeur X est dans B".

Lodewijk
la source
1
cela semble le plus pythonique qui maintient l'ordre. Je ne sais pas pourquoi ce n'est pas plus élevé! merci pour la grande solution!
Bill D
16
Il s'agit d'une solution O (n ^ 2), alors que les solutions ci-dessus sont O (n)
nareddyt
3
@nareddyt - faites bun set et vous aurez O (n)
jcchuks
2
@jcchuks L'avantage de cette solution est que vous devez conserver les doublons. Si vous pouvez être sûr de l'unicité, alors une solution d'ensemble O (n) serait mieux. Cependant, si les doublons ne sont pas possibles, pourquoi l'OP parle-t-il même de listes pour commencer? La notion d'intersection de liste est une absurdité mathématique
demongolem
63

Si vous convertissez la plus grande des deux listes en un ensemble, vous pouvez obtenir l'intersection de cet ensemble avec n'importe quel itérable en utilisant intersection():

a = [1,2,3,4,5]
b = [1,3,5,6]
set(a).intersection(b)
Brian R. Bondy
la source
9
Est-ce différentlist(set(a) & set(b))
user1767754
3
pourquoi importe quelle liste est convertie en set (en supposant n! = m)? quel est l'avantage de n'en convertir qu'un en set?
3pitt
1
Il semble que ce serait plus rapide
Nathan
29

Faites un ensemble à partir du plus grand:

_auxset = set(a)

Ensuite,

c = [x for x in b if x in _auxset]

fera ce que vous voulez (préserver bl'ordre, pas a- ne peut pas nécessairement préserver les deux ) et le faire rapidement . (L'utilisation if x in acomme condition dans la liste de compréhension fonctionnerait également et éviterait d'avoir à construire_auxset , mais malheureusement pour les listes de longueur substantielle, ce serait beaucoup plus lent).

Si vous souhaitez que le résultat soit trié, plutôt que de conserver l'ordre des listes, une méthode encore plus soignée pourrait être:

c = sorted(set(a).intersection(b))
Alex Martelli
la source
Ceci est presque certainement plus lent que la réponse acceptée mais a l'avantage que les doublons ne sont pas perdus.
tripleee
18

Voici du code Python 2 / Python 3 qui génère des informations de synchronisation pour les méthodes basées sur des listes et sur des ensembles pour trouver l'intersection de deux listes.

Les algorithmes de compréhension de liste pure sont O (n ^ 2), car insur une liste est une recherche linéaire. Les algorithmes basés sur les ensembles sont O (n), car la recherche d'ensembles est O (1), et la création d'ensembles est O (n) (et la conversion d'un ensemble en liste est également O (n)). Ainsi, pour des n suffisamment grands, les algorithmes basés sur les ensembles sont plus rapides, mais pour les petits n, les frais généraux de création des ensembles les rendent plus lents que les algorithmes de compilation de liste pure.

#!/usr/bin/env python

''' Time list- vs set-based list intersection
    See http://stackoverflow.com/q/3697432/4014959
    Written by PM 2Ring 2015.10.16
'''

from __future__ import print_function, division
from timeit import Timer

setup = 'from __main__ import a, b'
cmd_lista = '[u for u in a if u in b]'
cmd_listb = '[u for u in b if u in a]'

cmd_lcsa = 'sa=set(a);[u for u in b if u in sa]'

cmd_seta = 'list(set(a).intersection(b))'
cmd_setb = 'list(set(b).intersection(a))'

reps = 3
loops = 50000

def do_timing(heading, cmd, setup):
    t = Timer(cmd, setup)
    r = t.repeat(reps, loops)
    r.sort()
    print(heading, r)
    return r[0]

m = 10
nums = list(range(6 * m))

for n in range(1, m + 1):
    a = nums[:6*n:2]
    b = nums[:6*n:3]
    print('\nn =', n, len(a), len(b))
    #print('\nn = %d\n%s %d\n%s %d' % (n, a, len(a), b, len(b)))
    la = do_timing('lista', cmd_lista, setup) 
    lb = do_timing('listb', cmd_listb, setup) 
    lc = do_timing('lcsa ', cmd_lcsa, setup)
    sa = do_timing('seta ', cmd_seta, setup)
    sb = do_timing('setb ', cmd_setb, setup)
    print(la/sa, lb/sa, lc/sa, la/sb, lb/sb, lc/sb)

production

n = 1 3 2
lista [0.082171916961669922, 0.082588911056518555, 0.0898590087890625]
listb [0.069530963897705078, 0.070394992828369141, 0.075379848480224609]
lcsa  [0.11858987808227539, 0.1188349723815918, 0.12825107574462891]
seta  [0.26900982856750488, 0.26902294158935547, 0.27298116683959961]
setb  [0.27218389511108398, 0.27459001541137695, 0.34307217597961426]
0.305460649521 0.258469975867 0.440838458259 0.301898526833 0.255455833892 0.435697630214

n = 2 6 4
lista [0.15915989875793457, 0.16000485420227051, 0.16551494598388672]
listb [0.13000702857971191, 0.13060092926025391, 0.13543915748596191]
lcsa  [0.18650484085083008, 0.18742108345031738, 0.19513416290283203]
seta  [0.33592700958251953, 0.34001994132995605, 0.34146714210510254]
setb  [0.29436492919921875, 0.2953648567199707, 0.30039691925048828]
0.473793098554 0.387009751735 0.555194537893 0.540689066428 0.441652573672 0.633583767462

n = 3 9 6
lista [0.27657914161682129, 0.28098297119140625, 0.28311991691589355]
listb [0.21585917472839355, 0.21679902076721191, 0.22272896766662598]
lcsa  [0.22559309005737305, 0.2271728515625, 0.2323150634765625]
seta  [0.36382699012756348, 0.36453008651733398, 0.36750602722167969]
setb  [0.34979605674743652, 0.35533690452575684, 0.36164689064025879]
0.760194128313 0.59330170819 0.62005595016 0.790686848184 0.61710008036 0.644927481902

n = 4 12 8
lista [0.39616990089416504, 0.39746403694152832, 0.41129183769226074]
listb [0.33485794067382812, 0.33914685249328613, 0.37850618362426758]
lcsa  [0.27405810356140137, 0.2745978832244873, 0.28249192237854004]
seta  [0.39211201667785645, 0.39234519004821777, 0.39317893981933594]
setb  [0.36988520622253418, 0.37011313438415527, 0.37571001052856445]
1.01034878821 0.85398540833 0.698928091731 1.07106176249 0.905302334456 0.740927452493

n = 5 15 10
lista [0.56792402267456055, 0.57422614097595215, 0.57740211486816406]
listb [0.47309303283691406, 0.47619009017944336, 0.47628307342529297]
lcsa  [0.32805585861206055, 0.32813096046447754, 0.3349759578704834]
seta  [0.40036201477050781, 0.40322518348693848, 0.40548801422119141]
setb  [0.39103078842163086, 0.39722800254821777, 0.43811702728271484]
1.41852623806 1.18166313332 0.819398061028 1.45237674242 1.20986133789 0.838951479847

n = 6 18 12
lista [0.77897095680236816, 0.78187918663024902, 0.78467702865600586]
listb [0.629547119140625, 0.63210701942443848, 0.63321495056152344]
lcsa  [0.36563992500305176, 0.36638498306274414, 0.38175487518310547]
seta  [0.46695613861083984, 0.46992206573486328, 0.47583580017089844]
setb  [0.47616910934448242, 0.47661614418029785, 0.4850609302520752]
1.66818870637 1.34819326075 0.783028414812 1.63591241329 1.32210827369 0.767878297495

n = 7 21 14
lista [0.9703209400177002, 0.9734041690826416, 1.0182771682739258]
listb [0.82394003868103027, 0.82625699043273926, 0.82796716690063477]
lcsa  [0.40975093841552734, 0.41210508346557617, 0.42286920547485352]
seta  [0.5086359977722168, 0.50968098640441895, 0.51014018058776855]
setb  [0.48688101768493652, 0.4879908561706543, 0.49204087257385254]
1.90769222837 1.61990115188 0.805587768483 1.99293236904 1.69228211566 0.841583309951

n = 8 24 16
lista [1.204819917678833, 1.2206029891967773, 1.258256196975708]
listb [1.014998197555542, 1.0206191539764404, 1.0343101024627686]
lcsa  [0.50966787338256836, 0.51018595695495605, 0.51319599151611328]
seta  [0.50310111045837402, 0.50556015968322754, 0.51335406303405762]
setb  [0.51472997665405273, 0.51948785781860352, 0.52113485336303711]
2.39478683834 2.01748351664 1.01305257092 2.34068341135 1.97190418975 0.990165516871

n = 9 27 18
lista [1.511646032333374, 1.5133969783782959, 1.5639569759368896]
listb [1.2461750507354736, 1.254518985748291, 1.2613379955291748]
lcsa  [0.5565330982208252, 0.56119203567504883, 0.56451296806335449]
seta  [0.5966339111328125, 0.60275578498840332, 0.64791703224182129]
setb  [0.54694414138793945, 0.5508568286895752, 0.55375313758850098]
2.53362406013 2.08867620074 0.932788243907 2.76380331728 2.27843203069 1.01753187594

n = 10 30 20
lista [1.7777848243713379, 2.1453688144683838, 2.4085969924926758]
listb [1.5070111751556396, 1.5202279090881348, 1.5779800415039062]
lcsa  [0.5954139232635498, 0.59703707695007324, 0.60746097564697266]
seta  [0.61563014984130859, 0.62125110626220703, 0.62354087829589844]
setb  [0.56723213195800781, 0.57257509231567383, 0.57460403442382812]
2.88774814689 2.44791645689 0.967161734066 3.13413984189 2.6567803378 1.04968299523

Généré à l'aide d'une machine monocœur à 2 GHz avec 2 Go de RAM exécutant Python 2.6.6 sur une version Debian de Linux (avec Firefox fonctionnant en arrière-plan).

Ces chiffres ne sont qu'un guide approximatif, car les vitesses réelles des différents algorithmes sont affectées différemment par la proportion d'éléments qui se trouvent dans les deux listes de sources.

PM 2Ring
la source
11
a = [1,2,3,4,5]
b = [1,3,5,6]
c = list(set(a).intersection(set(b)))

Devrait fonctionner comme un rêve. Et, si vous le pouvez, utilisez des ensembles au lieu de listes pour éviter tout changement de ce type!

Alex Hart
la source
Si a et b sont grands, cela est plus rapide que les autres réponses
javadba
5

Une manière fonctionnelle peut être réalisée en utilisant filteret lambdaopérateur.

list1 = [1,2,3,4,5,6]

list2 = [2,4,6,9,10]

>>> list(filter(lambda x:x in list1, list2))

[2, 4, 6]

Edit: il filtre x qui existe à la fois dans list1 et list, la différence définie peut également être obtenue en utilisant:

>>> list(filter(lambda x:x not in list1, list2))
[9,10]

Edit2: python3 filterrenvoie un objet filtre, l'encapsulant avec listrenvoie la liste de sortie.

Saftophobie
la source
Veuillez utiliser le lien d' édition pour expliquer comment ce code fonctionne et ne pas simplement donner le code, car une explication est plus susceptible d'aider les futurs lecteurs. Voir aussi Comment répondre . source
Jed Fox
1
Avec Python3, cela renvoie un objet filtre. Vous devez dire list(filter(lambda x:x in list1, list2))pour l'obtenir sous forme de liste.
Adrian W
1

Ceci est un exemple lorsque vous avez besoin que chaque élément du résultat apparaisse autant de fois qu'il le montre dans les deux tableaux.

def intersection(nums1, nums2):
    #example:
    #nums1 = [1,2,2,1]
    #nums2 = [2,2]
    #output = [2,2]
    #find first 2 and remove from target, continue iterating

    target, iterate = [nums1, nums2] if len(nums2) >= len(nums1) else [nums2, nums1] #iterate will look into target

    if len(target) == 0:
            return []

    i = 0
    store = []
    while i < len(iterate):

         element = iterate[i]

         if element in target:
               store.append(element)
               target.remove(element)

         i += 1


    return store
Arturo Morales Rangel
la source
1

Il pourrait être en retard, mais je pensais juste que je devrais partager pour le cas où vous êtes obligé de le faire manuellement (montrer le travail - haha) OU lorsque vous avez besoin que tous les éléments apparaissent autant de fois que possible ou quand vous avez également besoin qu'il soit unique .

Veuillez noter que des tests ont également été écrits pour cela.



    from nose.tools import assert_equal

    '''
    Given two lists, print out the list of overlapping elements
    '''

    def overlap(l_a, l_b):
        '''
        compare the two lists l_a and l_b and return the overlapping
        elements (intersecting) between the two
        '''

        #edge case is when they are the same lists
        if l_a == l_b:
            return [] #no overlapping elements

        output = []

        if len(l_a) == len(l_b):
            for i in range(l_a): #same length so either one applies
                if l_a[i] in l_b:
                    output.append(l_a[i])

            #found all by now
            #return output #if repetition does not matter
            return list(set(output))

        else:
            #find the smallest and largest lists and go with that
            sm = l_a if len(l_a)  len(l_b) else l_b

            for i in range(len(sm)):
                if sm[i] in lg:
                    output.append(sm[i])

            #return output #if repetition does not matter
            return list(set(output))

    ## Test the Above Implementation

    a = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
    b = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
    exp = [1, 2, 3, 5, 8, 13]

    c = [4, 4, 5, 6]
    d = [5, 7, 4, 8 ,6 ] #assuming it is not ordered
    exp2 = [4, 5, 6]

    class TestOverlap(object):

        def test(self, sol):
            t = sol(a, b)
            assert_equal(t, exp)
            print('Comparing the two lists produces')
            print(t)

            t = sol(c, d)
            assert_equal(t, exp2)
            print('Comparing the two lists produces')
            print(t)

            print('All Tests Passed!!')

    t = TestOverlap()
    t.test(overlap)
anabeto93
la source
0

Si, par booléen ET, vous voulez dire les éléments qui apparaissent dans les deux listes, par exemple l'intersection, alors vous devriez regarder Python setet les frozensettypes.

Tim McNamara
la source
0

Vous pouvez également utiliser un compteur! Il ne conserve pas l'ordre, mais il prendra en compte les doublons:

>>> from collections import Counter
>>> a = [1,2,3,4,5]
>>> b = [1,3,5,6]
>>> d1, d2 = Counter(a), Counter(b)
>>> c = [n for n in d1.keys() & d2.keys() for _ in range(min(d1[n], d2[n]))]
>>> print(c)
[1,3,5]
Atonal
la source