2009-10-25 52 views
1

我喜欢用下面的语句用于组合名单在一起,有时:嵌套生成器表达式在Python函数调用的参数列表

>>> 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'。我想知道是否有人想过避免这种错误的方法,超越“不这样做”。

回答

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')] 
元组
+0

谢谢,产品功能看起来应该更安全,并导致更清晰的表达。 – 2009-10-25 15:36:36

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

在这种情况下,您可以将其全部放在一个列表理解中,但在某些情况下这样做更为复杂。为了清晰起见,我简化了示例。 – 2009-10-25 14:31:37

+2

为什么要把它粘在一条线上?为什么不只是嵌套循环?这将更加清晰,并且不需要建立任何中间名单。 – SilentGhost 2009-10-25 14:36:54

+0

但不是关于“发生器表达式”不工作的问题? – 2009-10-25 14:40:05

0

我要去推荐

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

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

它比您的解决方案系列更具可读性。花式是不是一件好事。