it-swarm.com.de

Schnittpunkt zweier verschachtelter Listen suchen?

Ich weiß, wie man eine Schnittmenge von zwei flachen Listen erhält:

b1 = [1,2,3,4,5,9,11,15]
b2 = [4,5,6,7,8]
b3 = [val for val in b1 if val in b2]

oder 

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

print intersect(b1, b2)

Wenn ich für verschachtelte Listen Schnittpunkte finden muss, beginnen meine Probleme:

c1 = [1, 6, 7, 10, 13, 28, 32, 41, 58, 63]
c2 = [[13, 17, 18, 21, 32], [7, 11, 13, 14, 28], [1, 5, 6, 8, 15, 16]]

Am Ende würde ich gerne erhalten:

c3 = [[13,32],[7,13,28],[1,6]]

Können Sie mir dabei helfen?

Verbunden

462
elfuego1

Falls Sie es wollen:

c1 = [1, 6, 7, 10, 13, 28, 32, 41, 58, 63]
c2 = [[13, 17, 18, 21, 32], [7, 11, 13, 14, 28], [1, 5, 6, 8, 15, 16]]
c3 = [[13, 32], [7, 13, 28], [1,6]]

Hier ist Ihre Lösung für Python 2:

c3 = [filter(lambda x: x in c1, sublist) for sublist in c2]

In Python 3 gibt filter eine iterable statt list zurück, sodass Sie filter-Aufrufe mit list():

c3 = [list(filter(lambda x: x in c1, sublist)) for sublist in c2]

Erklärung: 

Der Filterteil nimmt die Elemente jeder Unterliste und prüft, ob sie in der Quellliste c1 enthalten sind. .__ Das Listenverständnis wird für jede Unterliste in c2 ausgeführt. 

176
Brian R. Bondy

Sie müssen keine Kreuzung definieren. Es ist bereits ein erstklassiger Teil des Sets.

>>> b1 = [1,2,3,4,5,9,11,15]
>>> b2 = [4,5,6,7,8]
>>> set(b1).intersection(b2)
set([4, 5])
888
S.Lott

Für Leute, die nur nach dem Schnittpunkt zweier Listen suchen, stellte der Asker zwei Methoden zur Verfügung:

b1 = [1,2,3,4,5,9,11,15]
b2 = [4,5,6,7,8]
b3 = [val for val in b1 if val in b2]

und

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

print intersect(b1, b2)

Es gibt jedoch eine Hybridmethode, die effizienter ist, da Sie nur eine Konvertierung zwischen Liste/Satz und nicht nur drei Konvertierungen durchführen müssen:

b1 = [1,2,3,4,5]
b2 = [3,4,5,6]
s2 = set(b2)
b3 = [val for val in b1 if val in s2]

Dies wird in O (n) ausgeführt, während seine ursprüngliche Methode, die das Listenverständnis umfasst, in O (n ^ 2) ausgeführt wird.

59
Zack Burt

Der funktionale Ansatz:

input_list = [[1, 2, 3, 4, 5], [2, 3, 4, 5, 6], [3, 4, 5, 6, 7]]

result = reduce(set.intersection, map(set, input_list))

und es kann auf den allgemeineren Fall von 1+ Listen angewendet werden

27
pufferfish

Reine Listenverständnisversion

>>> c1 = [1, 6, 7, 10, 13, 28, 32, 41, 58, 63]
>>> c2 = [[13, 17, 18, 21, 32], [7, 11, 13, 14, 28], [1, 5, 6, 8, 15, 16]]
>>> c1set = frozenset(c1)

Abflachungsvariante:

>>> [n for lst in c2 for n in lst if n in c1set]
[13, 32, 7, 13, 28, 1, 6]

Verschachtelte Variante:

>>> [[n for n in lst if n in c1set] for lst in c2]
[[13, 32], [7, 13, 28], [1, 6]]
26
jfs

Der Operator & nimmt die Kreuzung zweier Sätze.

{1, 2, 3} & {2, 3, 4} Out [1]: {2, 3}

21
aflaisler

Eine pythonische Methode, um die Kreuzung von 2 Listen zu nehmen, ist:

[x for x in list1 if x in list2]
14
Flying_ostrich

Sie sollten diesen Code abflachen (entnommen aus http://kogs-www.informatik.uni-hamburg.de/~meine/python_tricks ). Der Code wurde nicht getestet, aber ich bin mir ziemlich sicher, dass er funktioniert:


def flatten(x):
    """flatten(sequence) -> list

    Returns a single, flat list which contains all elements retrieved
    from the sequence and all recursively contained sub-sequences
    (iterables).

    Examples:
    >>> [1, 2, [3,4], (5,6)]
    [1, 2, [3, 4], (5, 6)]
    >>> flatten([[[1,2,3], (42,None)], [4,5], [6], 7, MyVector(8,9,10)])
    [1, 2, 3, 42, None, 4, 5, 6, 7, 8, 9, 10]"""

    result = []
    for el in x:
        #if isinstance(el, (list, Tuple)):
        if hasattr(el, "__iter__") and not isinstance(el, basestring):
            result.extend(flatten(el))
        else:
            result.append(el)
    return result

Nachdem Sie die Liste reduziert haben, führen Sie die Kreuzung wie üblich aus:


c1 = [1, 6, 7, 10, 13, 28, 32, 41, 58, 63]
c2 = [[13, 17, 18, 21, 32], [7, 11, 13, 14, 28], [1, 5, 6, 8, 15, 16]]

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

print intersect(flatten(c1), flatten(c2))

8
Geo

Da intersect definiert wurde, reicht ein grundlegendes Listenverständnis aus:

>>> c3 = [intersect(c1, i) for i in c2]
>>> c3
[[32, 13], [28, 13, 7], [1, 6]]

Verbesserung dank der Bemerkung von S. Lott und der damit verbundenen Anmerkung von TM.:

>>> c3 = [list(set(c1).intersection(i)) for i in c2]
>>> c3
[[32, 13], [28, 13, 7], [1, 6]]
7
Emmanuel

Gegeben:

> c1 = [1, 6, 7, 10, 13, 28, 32, 41, 58, 63]

> c2 = [[13, 17, 18, 21, 32], [7, 11, 13, 14, 28], [1, 5, 6, 8, 15, 16]]

Ich finde den folgenden Code gut und vielleicht präziser, wenn Set-Operation verwendet wird:

> c3 = [list(set(f)&set(c1)) for f in c2] 

Es hat:

> [[32, 13], [28, 13, 7], [1, 6]]

Wenn auftrag benötigt:

> c3 = [sorted(list(set(f)&set(c1))) for f in c2] 

wir haben:

> [[13, 32], [7, 13, 28], [1, 6]]

Für einen Python-Style ist dieser übrigens auch in Ordnung:

> c3 = [ [i for i in set(f) if i in c1] for f in c2]
5
Steven

Ich weiß nicht, ob ich Ihre Frage zu spät beantworte. Nachdem ich Ihre Frage gelesen hatte, entwickelte ich eine Funktion intersect (), die sowohl auf der Liste als auch auf der verschachtelten Liste arbeiten kann. Ich habe Rekursion verwendet, um diese Funktion zu definieren, sie ist sehr intuitiv. Ich hoffe es ist was Sie suchen:

def intersect(a, b):
    result=[]
    for i in b:
        if isinstance(i,list):
            result.append(intersect(a,i))
        else:
            if i in a:
                 result.append(i)
    return result

Beispiel:

>>> c1 = [1, 6, 7, 10, 13, 28, 32, 41, 58, 63]
>>> c2 = [[13, 17, 18, 21, 32], [7, 11, 13, 14, 28], [1, 5, 6, 8, 15, 16]]
>>> print intersect(c1,c2)
[[13, 32], [7, 13, 28], [1, 6]]

>>> b1 = [1,2,3,4,5,9,11,15]
>>> b2 = [4,5,6,7,8]
>>> print intersect(b1,b2)
[4, 5]
3
Mrsky Boatin

Betrachten Sie [1,2] als Schnittpunkt mit [1, [2]]? Sind es nur die Zahlen, die Sie interessieren, oder auch die Listenstruktur?

Wenn nur die Zahlen vorhanden sind, prüfen Sie, wie die Listen "abgeflacht" werden sollen, und verwenden Sie dann die set()-Methode.

3
unwind

Ich suchte auch nach einem Weg, es zu tun, und schließlich endete es so:

def compareLists(a,b):
    removed = [x for x in a if x not in b]
    added = [x for x in b if x not in a]
    overlap = [x for x in a if x in b]
    return [removed,added,overlap]
1

Um eine Schnittmenge zu definieren, die die Kardinalität der Elemente korrekt berücksichtigt, verwenden Sie Counter

from collections import Counter

>>> c1 = [1, 2, 2, 3, 4, 4, 4]
>>> c2 = [1, 2, 4, 4, 4, 4, 5]
>>> list((Counter(c1) & Counter(c2)).elements())
[1, 2, 4, 4, 4]
1
James Hirschorn
c1 = [1, 6, 7, 10, 13, 28, 32, 41, 58, 63]
c2 = [[13, 17, 18, 21, 32], [7, 11, 13, 14, 28], [1, 5, 6, 8, 15, 16]]
c3 = [list(set(i) & set(c1)) for i in c2]
c3
[[32, 13], [28, 13, 7], [1, 6]]

Für mich ist das ein sehr eleganter und schneller Weg dazu :)

0
Michal
c1 = [1, 6, 7, 10, 13, 28, 32, 41, 58, 63]

c2 = [[13, 17, 18, 21, 32], [7, 11, 13, 14, 28], [1, 5, 6, 8, 15, 16]]

c3 = [list(set(c2[i]).intersection(set(c1))) for i in xrange(len(c2))]

c3
->[[32, 13], [28, 13, 7], [1, 6]]
0
user3105897

Wir können dazu Set-Methoden verwenden:

c1 = [1, 6, 7, 10, 13, 28, 32, 41, 58, 63]
c2 = [[13, 17, 18, 21, 32], [7, 11, 13, 14, 28], [1, 5, 6, 8, 15, 16]]

   result = [] 
   for li in c2:
       res = set(li) & set(c1)
       result.append(list(res))

   print result
0
Birendra Kumar

eine flache Liste kann einfach über reduce erstellt werden.

Alles, was Sie brauchen, um Initializer - drittes Argument in der Funktion reduce zu verwenden.

reduce(
   lambda result, _list: result.append(
       list(set(_list)&set(c1)) 
     ) or result, 
   c2, 
   [])

Der obige Code funktioniert sowohl für python2 als auch für python3, aber Sie müssen das Reduktionsmodul als from functools import reduce importieren. Weitere Informationen finden Sie unter dem folgenden Link.

0
Raja Sakthiyan
# Problem:  Given c1 and c2:
c1 = [1, 6, 7, 10, 13, 28, 32, 41, 58, 63]
c2 = [[13, 17, 18, 21, 32], [7, 11, 13, 14, 28], [1, 5, 6, 8, 15, 16]]
# how do you get c3 to be [[13, 32], [7, 13, 28], [1, 6]] ?

Hier ist eine Möglichkeit, c3 festzulegen, für die keine Sets erforderlich sind:

c3 = []
for sublist in c2:
    c3.append([val for val in c1 if val in sublist])

Wenn Sie jedoch nur eine Zeile verwenden möchten, können Sie Folgendes tun:

c3 = [[val for val in c1 if val in sublist]  for sublist in c2]

Es ist ein Listenverständnis innerhalb eines Listenverständnisses, das etwas ungewöhnlich ist, aber ich denke, Sie sollten nicht zu viel Mühe haben, es zu verfolgen.

0
J-L