python list comprehension在一次迭代中生成两个值

use*_*366 42 python list-comprehension list

我想在python中生成一个列表如下 -

[1, 1, 2, 4, 3, 9, 4, 16, 5, 25 .....]
Run Code Online (Sandbox Code Playgroud)

你会想通的,它只不过是 n, n*n

我尝试在python中编写这样的列表理解如下 -

lst_gen = [i, i*i for i in range(1, 10)]
Run Code Online (Sandbox Code Playgroud)

但这样做会产生语法错误.

通过列表理解生成上面列表的好方法是什么?

Ash*_*ary 44

用途itertools.chain.from_iterable:

>>> from itertools import chain
>>> list(chain.from_iterable((i, i**2) for i in xrange(1, 6)))
[1, 1, 2, 4, 3, 9, 4, 16, 5, 25]
Run Code Online (Sandbox Code Playgroud)

或者您也可以使用生成器功能:

>>> def solve(n):
...     for i in xrange(1,n+1):
...         yield i
...         yield i**2

>>> list(solve(5))
[1, 1, 2, 4, 3, 9, 4, 16, 5, 25]
Run Code Online (Sandbox Code Playgroud)


小智 16

问题是陈旧的,但只是对于好奇的读者,我提出了另一种可能性:正如第一篇文章所述,你可以从一个数字列表轻松地制作一对(i,i**2).然后你想要压扁这对夫妻.因此,只需在理解中添加展平操作即可.

[x for i in range(1, 10) for x in (i,i**2)]
Run Code Online (Sandbox Code Playgroud)


Joh*_*all 7

您可以创建一个列表列表,然后使用reduce 来连接它们。

print [[n,n*n] for n in range (10)]
Run Code Online (Sandbox Code Playgroud)

[[0, 0], [1, 1], [2, 4], [3, 9], [4, 16], [5, 25], [6, 36], [7, 49], [ 8, 64], [9, 81]]

print reduce(lambda x1,x2:x1+x2,[[n,n*n] for n in range (10)])
Run Code Online (Sandbox Code Playgroud)

[0、0、1、1、2、4、3、9、4、16、5、25、6、36、7、49、8、64、9、81]

 print reduce(lambda x1,x2:x1+x2,[[n**e for e in range(1,4)]\
 for n in range (1,10)])
Run Code Online (Sandbox Code Playgroud)

[1, 1, 1, 2, 4, 8, 3, 9, 27, 4, 16, 64, 5, 25, 125, 6, 36, 216, 7, 49, 343, 8, 64, 512, 9 , 81, 729]

Reduce 采用一个可调用表达式,该表达式采用两个参数并从前两项开始处理序列。最后一个表达式的结果将用作后续调用中的第一项。在这种情况下,每个列表都会被依次添加到列表列表中的第一个列表,然后返回该列表作为结果。

列表推导式使用“ for var inequence ”表达式定义的变量和序列,通过 lambda 表达式隐式调用 map。下面的也是同样的情况。

map(lambda n:[n,n*n],range(1,10))
Run Code Online (Sandbox Code Playgroud)

[[1, 1], [2, 4], [3, 9], [4, 16], [5, 25], [6, 36], [7, 49], [8, 64], [ 9, 81]]

我不知道还有更自然的reduce python 表达式。


Jon*_*yer 6

一个鲜为人知的技巧:列表推导可以有多个for子句.

例如:

>>> [10*x+y for x in range(4) for y in range(3)]
[0, 1, 2, 10, 11, 12, 20, 21, 22, 30, 31, 32]
Run Code Online (Sandbox Code Playgroud)

在您的特定情况下,您可以:

>>> [x*x if y else x for x in range(5) for y in range(2)]
[0, 0, 1, 1, 2, 4, 3, 9, 4, 16]
Run Code Online (Sandbox Code Playgroud)


Jor*_*ley 5

lst_gen = sum([(i, i*i) for i in range(1, 10)],())
Run Code Online (Sandbox Code Playgroud)

哦,我应该提到总和可能打破一个迭代规则:(

  • 虽然这样可行,但使用"sum"这种方式会产生二次性能,因此有一种危险的习惯. (3认同)
  • @DSM,请原谅我的无知,为什么将“ sum()”与(元组的)列表理解一起使用会产生二次性能?我的问题的一部分是,“这种方式”的哪个方面是问题? (2认同)

Mar*_*ers 5

列表推导一次生成一个元素.相反,您的选择是将循环更改为一次只生成一个值:

[(i//2)**2 if i % 2 else i//2 for i in range(2, 20)]
Run Code Online (Sandbox Code Playgroud)

或者生成元组然后使用itertools.chain.from_iterable()以下方法展平列表:

from itertools import chain

list(chain.from_iterable((i, i*i) for i in range(1, 10)))
Run Code Online (Sandbox Code Playgroud)

输出:

>>> [(i//2)**2 if i % 2 else i//2 for i in range(2, 20)]
[1, 1, 2, 4, 3, 9, 4, 16, 5, 25, 6, 36, 7, 49, 8, 64, 9, 81]
>>> list(chain.from_iterable((i, i*i) for i in range(1, 10)))
[1, 1, 2, 4, 3, 9, 4, 16, 5, 25, 6, 36, 7, 49, 8, 64, 9, 81]
Run Code Online (Sandbox Code Playgroud)

  • 我不知道我是否应该被第一个解决方案着迷或反感 (3认同)