2017-06-11 3 views
0

Ich habe ein großes Diktat: 600 Schlüssel mit Elementen = große Liste (etwa 10000-20000 Elemente).Erhalten Sie alle möglichen Paare aus mehreren großen Listen

Mein Ziel ist es, Paare aus jeder Liste in dict zu bekommen und es in einer Liste zusammenzuführen.

z. Ich habe:

d1 = {'key1': ['a', 'b', 'c', 'd'], 'key2': ['f', 'a']} 

Erwartetes Ergebnis:

d2 = ['a_b', 'a_c', 'a_d', 'b_c', 'b_d', 'c_d', 'a_f'] 

Mein Code:

d2 = [] 
for k, v in d1.items(): 
    for i, j in itertools.product(v, v): 
     if i>j: 
      a = "_".join(list(set([i, j]))) 
      d2.append(a) 

Und ich habe ein Problem: in Terminal mein Python-Skript sagt 'getötet'.

Dies ist wahrscheinlich auf unangemessenen Speicherverbrauch zurückzuführen. Gibt es Möglichkeiten, dieses Problem zu lösen?

Antwort

6

Was Sie beschreiben, ist kein product, aber combinations.

Außerdem , wenn der Speicher ein Problem ist, verwenden Sie besser einen Generator so:

from itertools import combinations 

def dic_comb_generator(d1): 
    for v in d1.values(): 
     for t in combinations(sorted(v),2): 
      yield "%s_%s"%t

wir die Elemente in v solche Hier sorted(..) zur ersten Art verwenden, dass die resultierende Tupel als auch sortiert werden. Falls Sie nicht möchten, die zu sortierenden Kombinationen, aber in der Reihenfolge der Liste auftreten, sollten Sie die sorted(..) Funktion entfernen. Außerdem verwenden wir 2, da wir Kombinationen (Tupel) mit zwei Elementen konstruieren.

Wenn wir den Ausgang materialisieren, erhalten wir:

>>> list(dic_comb_generator({'key1': ['a', 'b', 'c', 'd'], 'key2': ['f', 'a']})) 
['a_b', 'a_c', 'a_d', 'b_c', 'b_d', 'c_d', 'a_f'] 

Aber wenn Sie den Generator in einer for Schleife verwenden, wie:

for elem in dic_comb_generator(d1): 
    print(elem) 

Python wird keine Liste mit allen Elementen konstruieren: Alle Elemente werden generiert, aber wenn Sie sie nicht speichern, kann der für das erste Element verwendete Speicher für das zweite Element wiederverwendet werden. Insbesondere im Zusammenhang mit Produkten, Kombinationen, ... wo die Anzahl der Elemente sehr groß sein kann, kann sich dies auszahlen: Das Speichern einer Liste von 100M + führt zu einer enormen Speicherbelastung, während die Handhabung eines Elements zu der Zeit eine konstante Speichernutzung hat.

+0

vielen Dank!Und wie kann ich Counter auf Generator anwenden? – uzver

+0

@uzver: einfach 'Counter (dic_comb_generator (d1))'. –

+0

Das verursacht einen Speicherfehler :( – uzver

3

Man könnte so etwas tun:

import itertools as it 
for l in d1.values(): 
    for t in it.combinations(sorted(l), 2): 
     print("_".join(t)) 

Zeige:

a_b 
a_c 
a_d 
b_c 
b_d 
c_d 
a_f 

Hinweis: Wenn Sie es sortiert werden nicht wollen, einfach die sorted Funktionsaufruf herausnehmen.

+0

Was ist, wenn OP nicht so sortiert werden soll? A, b , c, d ist nur ein repräsentatives Beispiel, aber was ist, wenn die Eingabe w, g, k, l ist? –

+0

@Coldspeed In seinem Beispielcode gab es eine 'if i> j'-Klausel, die mich zu der Annahme brachte, dass er es wollte Sortiert. Aber ich werde eine Notiz darüber hinzufügen. Danke für das Bemerken. – rassar

1

Sie einen Generator erstellen können, die nicht itertools mit sich bringt:

def dic_comb_generator(d): 
    for val in d.values(): 
     v = sorted(val) 
     for i in range(len(v)): 
      for j in range(i+1, len(v)): 
       yield v[i] + '_' + v[j] 
Verwandte Themen