Nesting-Generator Ausdrücke in der Argumentliste für einen Python-Funktionsaufruf
-
06-07-2019 - |
Frage
Ich mag das folgende Idiom verwenden, um Listen zusammen kombiniert, manchmal:
>>> list(itertools.chain(*[[(e, n) for e in l] for n, l in (('a', [1,2]),('b',[3,4]))]))
[(1, 'a'), (2, 'a'), (3, 'b'), (4, 'b')]
(ich weiß, es gibt einfachere Wege, um dieses bestimmtes Ergebnis zu bekommen, aber es kommt ist praktisch, wenn Sie über die Elemente in Listen von Listen von Listen zu durchlaufen wollen, oder so ähnlich. Das Problem ist, wenn Sie Generator verwenden Ausdrücke, dies wird fehleranfällig. Eg
>>> list(itertools.chain(*(((e, n) for e in l) for n, l in (('a', [1,2]),('b',[3,4])))))
[(1, 'b'), (2, 'b'), (3, 'b'), (4, 'b')]
Was hier passiert, ist, dass die inneren Generator Ausdrücke übergeben bekommen als Argumente an itertools.chain
, so bei der die Zeit, die sie ausgewertet sind, hat der äußere Generator Ausdruck abgeschlossen, und n
an seinem Endwert, 'b'
fixiert. Ich frage mich, ob jemand hat Möglichkeiten gedacht, diese Art von Fehler zu vermeiden, darüber hinaus „tun das nicht.“
Lösung
Ihr Ansatz fast funktioniert, brauchen Sie nur die Generatoren zu glätten. Sehen Sie, wie die for e in l
bis ganz nach rechts bewegt wird,
>>> list(itertools.chain((e, n) for n, l in (('a', [1,2]),('b',[3,4])) for e in l ))
[(1, 'a'), (2, 'a'), (3, 'b'), (4, 'b')]
Hier ist, wie die gleiche Sache zu tun mit itertools.product
>>> X=itertools.chain(*(itertools.product(*i[::-1]) for i in (('a', [1,2]),('b',[3,4]))))
>>> print list(X)
[(1, 'a'), (2, 'a'), (3, 'b'), (4, 'b')]
oder wenn Sie berechtigt sind, die Tupel um
wechseln>>> X=itertools.chain(*(itertools.product(*i) for i in (([1,2],'a'),([3,4],'b'))))
>>> print list(X)
[(1, 'a'), (2, 'a'), (3, 'b'), (4, 'b')]
Andere Tipps
würde nicht ein verschachtelte Liste Verständnis besser geeignet sein?
>>> tt = (('a', [1,2]),('b',[3,4]))
>>> [(s, i) for i, l in tt for s in l]
[(1, 'a'), (2, 'a'), (3, 'b'), (4, 'b')]
Ich werde vorschlagen
data = (('a', [1,2]), ('b', [3,4]))
result = []
for letter, numbers in data:
for number in numbers:
result.append((number, letter))
Es ist viel besser lesbar als Ihre Lösung Familie. Fancy ist nicht eine gute Sache.