2017-12-26 4 views
3

Ich habe einen Generator, und ich möchte eine verschachtelte Schleife so ausführen, dass die innere Schleife an der Stelle beginnt, an der die äußere Schleife gerade steht. Zum Beispiel habe ich einen Generator, der die Liste [1,2,3] erzeugt, und meine Schleife sollte produzieren: (1,2),(1,3),(2,3). Der Code, den ich herauskommen, ist der folgende:Klonen eines Generators für ein kartesisches Produkt ohne Duplikate

from itertools import tee 

def my_gen(): 
    my_list = [1, 2, 3] 
    for x in my_list: 
     yield x 

first_it = my_gen() 
while True: 
    try: 
     a = next(first_it) 
     first_it, second_it = tee(first_it) 
     for b in second_it: 
      print(a,b) 
    except StopIteration: 
     break 

Dieser Code umständlich ist, nicht effizient und sieht nicht sehr pythonic mir. Bitte beachten Sie, dass ich combinations_with_replacement nicht verwenden kann, da ich eine innere Schleife für die Verarbeitung eines bestimmten Werts aus der äußeren Schleife benötige.

Irgendwelche Vorschläge für einen eleganteren und pythonischen Code?

+0

Mögliches Duplikat [Python: Rückkehr einzigartig nur kartesisches Produkts einer Liste mit Listen] (https://stackoverflow.com/questions/19946195/ Python-Return-Unique-Only-Cartesian-Produkt-einer-Liste-enthält-Listen) –

Antwort

3

Das wiederholte Klonen und Ausstoßen von nur einem der resultierenden Iteratoren ist nicht sehr effizient. Gemäß der itertools.tee docs:

Im Allgemeinen, wenn ein Iterator verwendet die meisten oder alle Daten, bevor eine andere Iterator beginnt, ist es schneller Liste zu verwenden() anstelle von T-Stück().

from itertools import islice 

my_list = [1, 2, 3] 
# or, more generally 
# my_list = list(my_gen()) 

for i, a in enumerate(my_list): 
    for b in islice(my_list, i+1, None): 
     print((a, b)) 
(1, 2) 
(1, 3) 
(2, 3) 
+0

Dies ist eine gute Antwort, aber ich würde lieber mit einem Generatoren bleiben, und nicht mit Listen arbeiten. – Gino

+1

@Gino Generatoren werden normalerweise verwendet, um zu vermeiden, dass viele Dinge in den Speicher geladen werden. Die Verwendung eines T-Stücks hat grundsätzlich eine Liste hinter den Kulissen, die während der Iteration gefüllt und geleert wird, während die andere iteriert wird. Die Verwendung eines T-Stücks und das Iterieren über eins bis zum Ende ist dasselbe wie das Laden des gesamten Generators in den Speicher, so dass eine Liste nicht schadet. – Artyer

0

Das Ergebnis (1,2),(1,3),(2,3) ist nicht das Kreuzprodukt. Willst du alle Kombinationen ohne Wiederholung erhalten?

Für Kombinationen ohne Wiederholung

Verwenden itertools.combinations Funktion:

from itertools import combinations 

print(list(combinations([1,2,3], 2))) 

Für aktuelle kartesisches Produkt

Mit Liste Begreifen Sie Ihren Code in eine pythonic und elegante Art und Weise reduzieren :

my_list = [1, 2, 3] 

c_prod = [(i, j) for i in iter(my_list) for j in iter(my_list)] 

print(c_prod) 

andere Wahl ist die itertools.product Funktion zu verwenden:

import itertools 

for i in itertools.product(my_list, my_list): 
    print(i)