2010-04-28 7 views
11

Ich möchte die gleichen Elemente von zwei Listen zählen. Listen können doppelte Elemente enthalten, daher kann ich diese nicht in Sätze konvertieren und & operator verwenden.Gemeinsame Elemente zwischen zwei Listen, die keine Sätze in Python verwenden

a=[2,2,1,1] 
b=[1,1,3,3] 

Satz (a) & Satz (b) arbeiten
ein & b funktionieren nicht

Es ist möglich, es zu tun withoud gesetzt und dictonary?

+0

Warum nicht Sets verwenden möchten? –

+1

Ich habe doppelte Elemente in der Liste – Thomas

+2

Was sind die erwarteten Rückgabewerte für '[1, 2, 1]' und '[1, 3, 2]'? – SilentGhost

Antwort

8

Verwenden von Sets ist am effizientesten, aber Sie könnten immer r = [i for i in l1 if i in l2] tun.

+0

Ein deutlicher Unterschied: Die vorgeschlagene Methode set() & set() gibt einen einzelnen Wert zurück, der den beiden Listen gemeinsam ist (set ([1]) in diesem Beispiel), während Ihre Lösung [1, 1] usw. zurückgibt auf. –

+0

Danke, aber ist es mehr Performance-Lösung? – Thomas

+0

Ich will Funktion, die zurück [1,1] – Thomas

11

In Python 3.x (und Python 2.7, wenn es freigegeben wird), können Sie collections.Counter für diesen Einsatz:

>>> from collections import Counter 
>>> list((Counter([2,2,1,1]) & Counter([1,3,3,1])).elements()) 
[1, 1] 

Hier ist eine alternative collections.defaultdict (erhältlich in Python 2.5 und höher). Es hat die nette Eigenschaft, dass die Reihenfolge des Ergebnisses deterministisch ist (es entspricht im Wesentlichen der Reihenfolge der zweiten Liste).

from collections import defaultdict 

def list_intersection(list1, list2): 
    bag = defaultdict(int) 
    for elt in list1: 
     bag[elt] += 1 

    result = [] 
    for elt in list2: 
     if elt in bag: 
      # remove elt from bag, making sure 
      # that bag counts are kept positive 
      if bag[elt] == 1: 
       del bag[elt] 
      else: 
       bag[elt] -= 1 
      result.append(elt) 

    return result 

für diese beiden Lösungen, die Anzahl des Auftretens eines gegebenen Elements x in der Ausgabeliste ist das Minimum der Anzahl der Vorkommen von x in den beiden Eingangslisten. Es ist nicht klar aus deiner Frage, ob dies das gewünschte Verhalten ist.

+0

'if bag [elt]:' Fügt dem Beutel einen Gegenstand 'elt: 0' hinzu, wenn 'elt in bag' falsch ist. Wenn (wie das OP andeutet) nur wenige Duplikate vorhanden sind, kann es besser sein, wenn man in Tasche und Tasche steckt: sonst kann die Tasche mit nutzlosen 0-Werten aufgebläht werden. –

+0

@ John Machin: Hmm. Guter Punkt. Eine Alternative wäre es, sicherzustellen, dass die Anzahl der Beutel immer streng positiv ist, indem man "Beutel [elt] - = 1" mit einem "wenn nicht Beutel [elt]: del bag [elt]" befolgt. Dann könnte der 'if' Test einfach' ift elt in bag: 'sein, was schöner liest. Ich werde die Antwort bearbeiten. –

0

SilentGhost, Mark Dickinson und Lo'oris recht, Vielen Dank für Bericht dieses Problem - ich brauche gemeinsamen Teil von Listen, so für:

a = [1,1,1,2]

b = [1,1,3,3]

Ergebnis sein sollte [1,1]

Sorry für Kommentar in nicht geeigneten Ort - ich heute registriert haben.

I modifizierte Ihnen Lösungen:

def count_common(l1,l2): 
     l2_copy=list(l2) 
     counter=0 
     for i in l1: 
      if i in l2_copy: 
       counter+=1 
       l2_copy.remove(i) 
     return counter 

l1=[1,1,1] 
l2=[1,2] 
print count_common(l1,l2) 

+4

willkommen! Eventuell möchten Sie eine E-Mail an "team @ stackoverflow.com" senden und sie bitten, Ihr neu registriertes Konto mit dem vorherigen temporären Konto zusammenzuführen. Siehe: http://meta.stackexchange.com/questions/18232/how-can-one-link-merge-combine-associate-two-stack-overflow-accounts-users-anon –

Verwandte Themen