2

到目前为止,在 Python 中,我只见过指定一次包含一个元素的列表推导。例如,它们都采用以下形式

[f(x) for x in <iterable>]

有没有办法一次指定多个元素?例如,

[f(x), g(x) for x in <iterable>]

我问是因为我想创建一个列表推导来计算某个数字 x 的所有除数,但我想尽可能有效地做到这一点。现在我正在使用以下内容,

[y for y in range(1,x+1) if x%y == 0]

但我想做这样的事情,

[y, x/y for y in range(1, sqrt(x)+1) if x%y == 0]

因为这样会更有效率。顺便说一句,我没有这样做的实际理由。有人告诉我,这只是一个具有挑战性的问题,目标是尽可能用最小、最有效的列表理解来完成。

提前致谢。

编辑:好的,看起来我必须使用元组。我试图避免这种情况,因为我必须创建另一个函数来展平列表,这会使我的解决方案更长。

编辑2:以防万一有人偶然发现这个问题,我在原来的问题中想要做的答案是这样的:

[y for x in <iterable> for y in f(x), g(x)]

它在列表推导中使用嵌套的 for 循环来完成工作。

4

5 回答 5

5

您可以将其展平到位

[y if i else x/y for y in range(1, sqrt(x)+1) for i in 0,1 if x%y == 0]
于 2012-07-18T04:53:25.087 回答
3

您可以分配给元组

[(y, x/y) for y in range(1, int(sqrt(x))+1) if x%y == 0]

与您的基本问题无关,但与您的示例无关:我必须将第二个参数转换range()为 an,int因为在我的测试代码中sqrt()导致了 a 。float

更新重新编辑帖子:

要展平这个元组列表:

In [24]: s
Out[24]: [(1, 20), (2, 10), (4, 5)]

用这个:

In [25]: import operator

创建一个元组:

In [26]: reduce(operator.add, s, ())
Out[26]: (1, 20, 2, 10, 4, 5)

创建一个列表:

In [27]: list(reduce(operator.add, s, ()))
Out[27]: [1, 20, 2, 10, 4, 5]

注意:@jamylak 在有用的评论中指出,reduce运行operator.add顺序为 O(N^2),使用itertools.chain会更有效率。随着列表大小的增加,这变得更加重要,在这种情况下应该考虑。

于 2012-07-18T04:04:49.770 回答
3

是的,你可以做到。您只需要在元素周围加上括号。你得到的是一个元组列表。

>>> [(x, x+1) for x in range(5)]
[(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)]
于 2012-07-18T04:04:56.343 回答
2

哦,这么近:

[(y, x/y) for y in range(1, sqrt(x)+1) if x%y == 0]

可以生成一个元组列表,这些当然可以包含多个值。

于 2012-07-18T04:04:31.443 回答
1

是的,绝对是,只需在值周围使用括号:

[(y, x/y) for y in range(1, sqrt(x)+1) if x%y == 0]
于 2012-07-18T04:05:04.907 回答