在Python函数调用参数列表中嵌套生成器表达式

1 投票
3 回答
1371 浏览
提问于 2025-04-15 15:21

我有时候喜欢用以下这种方式来把列表合并在一起:

>>> 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')]

(我知道有更简单的方法可以得到这个结果,但这种方式在你想要遍历嵌套列表的时候会很有用。问题是,当你使用生成器表达式时,这种方式容易出错。例如:

>>> 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')]

这里发生的事情是,内部的生成器表达式被当作参数传递给了 itertools.chain,所以在它们被计算的时候,外部的生成器表达式已经结束了,n 的值也固定在了最后的值 'b'。我在想,除了“别这么做”之外,还有没有人想过避免这种错误的方法。

3 个回答

0

我想建议一下

data = (('a', [1,2]), ('b', [3,4]))

result = []
for letter, numbers in data:
     for number in numbers:
         result.append((number, letter))

这个比你的解决方案要容易读懂多了。花哨的东西并不好。

6

嵌套的列表推导式是不是更合适呢?

>>> 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')]
2

你的方法差不多可以用,只需要把生成器“压平”一下。看看这个 for e in l 是怎么被移到最右边的。

>>> 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')]

这里有一个使用 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')]

或者如果你可以调整一下元组的位置。

>>> 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')]

撰写回答