Nesting generator expressions in the argument list for a python function call
I like to use the following idiom for combining lists together, sometimes:
>>> 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')]
(I know there are easier ways to get this particular result, but it comes comes in handy when you want to iterate over the elements in lists of lists of lists, or something like that. The trouble is, when you use generator expressions, this becomes error prone. E.g.
>>> 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')]
What's happening here is that the inner generator expressions get passed as arguments to itertools.chain
, so at the the time they're evaluated, the outer generator expression has finished, and n
is fixed at its final value, 'b'
. I'开发者_如何学运维m wondering whether anyone has thought of ways to avoid this kind of error, beyond "don't do that."
wouldn't a nested list comprehension be more appropriate?
>>> 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')]
Your approach almost works, you just need to flatten the generators. See how the for e in l
is moved to the very right
>>> 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')]
Here is how to do the same thing using 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')]
or if you are allowed to switch the tuples around
>>> 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')]
I'm going to suggest
data = (('a', [1,2]), ('b', [3,4]))
result = []
for letter, numbers in data:
for number in numbers:
result.append((number, letter))
It's a lot more readable than your solution family. Fancy is not a good thing.
精彩评论