12

有没有办法在列表/字典/集合理解中每次迭代输出两个(或更多)项目?举个简单的例子,输出 1 到 3 的所有整数的正负双精度(也就是{x | x = ±2n, n ∈ {1...3}}),有没有类似下面这样的语法?

>>> [2*i, -2*i for i in range(1, 4)]
[2, -2, 4, -4, 6, -6]

我知道我可以输出元组(+i,-i)并将其展平,但我想知道是否有任何方法可以使用单一理解完全解决问题。

目前,我正在生成两个列表并将它们连接起来(如果顺序不重要,这可行):

>>> [2*i for i in range(1, 4)] + [-2*i for i in range(1, 4)]
[2, 4, 6, -2, -4, -6]
4

5 回答 5

10

Another form of nested comprehension:

>>> [sub for i in range(1, 4) for sub in (2*i, -2*i)]
[2, -2, 4, -4, 6, -6]
于 2013-03-22T18:41:53.400 回答
10

另一种选择是嵌套推导:

r = [2*i*s for i in range(1, 4) for s in 1, -1]

对于更一般的情况:

r = [item for tpl in (<something that yields tuples>) for item in tpl]

用你原来的例子:

r = [item for tpl in ((2*i, -2*i) for i in range(1, 4)) for item in tpl]

尽管我真的会itertools.chain.from_iterable像@Lattyware 所说的那样建议。

于 2013-03-20T22:28:43.110 回答
7

itertools.chain.from_iterable()正如您所提到的,这里最好的答案是简单地使用来展平列表:

itertools.chain.from_iterable((2*i, -2*i) for i in range(1, 4))

这是非常易读的,并且不需要对源进行两次迭代(这可能是有问题的,因为某些迭代器可能会耗尽,这意味着额外的计算工作)。

于 2013-03-20T22:25:12.603 回答
4

虽然我会使用itertools@Lattyware 建议的方法,但这里有一个更通用的方法,使用生成器也可能会有所帮助。

>>> def nums():
        for i in range(1, 4):
            yield 2*i
            yield -2*i


>>> list(nums())
[2, -2, 4, -4, 6, -6]
于 2013-03-20T22:27:32.993 回答
2

根据PEP202,无法从列表推导中输出多个对象:

- 表格[x, y for ...]不被允许;一个是需要写的 [(x, y) for ...]

于 2013-03-20T22:31:14.353 回答