62

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

[1, 1, 2, 4, 3, 9, 4, 16, 5, 25 .....]

你会发现,这不过是n, n*n

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

lst_gen = [i, i*i for i in range(1, 10)]

但是这样做会产生语法错误。

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

4

13 回答 13

54

使用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]

或者您也可以使用生成器函数:

>>> 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]
于 2013-05-16T18:35:18.280 回答
44

这个问题很老,但只是为了好奇的读者,我提出了另一种可能性:如第一篇文章所述,您可以轻松地从数字列表中制作一对 (i, i**2)。然后你想把这对夫妇弄平。因此,只需在您的理解中添加 flatten 操作即可。

[x for i in range(1, 10) for x in (i,i**2)]
于 2016-10-26T14:50:28.690 回答
10

一个鲜为人知的技巧:列表推导式可以有多个 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]

在您的特定情况下,您可以执行以下操作:

>>> [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]
于 2017-04-07T19:01:29.660 回答
7

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

[(i//2)**2 if i % 2 else i//2 for i in range(2, 20)]

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

from itertools import chain

list(chain.from_iterable((i, i*i) for i in range(1, 10)))

输出:

>>> [(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]
于 2013-05-16T18:38:04.577 回答
5
lst_gen = sum([(i, i*i) for i in range(1, 10)],())

哦,我应该提到总和可能违反了一次迭代规则:(

于 2013-05-16T18:36:00.840 回答
4

您可以创建一个列表列表,然后使用 reduce 加入它们。

print [[n,n*n] for n in range (10)]

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

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

[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 in sequence”表达式定义的变量和序列隐式调用带有 lambda 表达式的 map 。以下是同样的事情。

map(lambda n:[n,n*n],range(1,10))

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

我不知道用于 reduce 的更自然的 python 表达式。

于 2013-05-16T19:25:20.447 回答
2

另一种选择,对某些人来说可能看起来很反常

>>> from itertools import izip, tee
>>> g = xrange(1, 11)
>>> x, y = tee(g)
>>> y = (i**2 for i in y)
>>> z = izip(x, y)
>>> output = []
>>> for k in z:
...     output.extend(k)
... 
>>> print output
[1, 1, 2, 4, 3, 9, 4, 16, 5, 25, 6, 36, 7, 49, 8, 64, 9, 81, 10, 100]
于 2013-05-16T19:10:33.983 回答
1

另外的选择:

reduce(lambda x,y: x + [y, y*y], range(1,10), [])
于 2013-05-16T18:38:41.767 回答
1
>>> lst_gen = [[i, i*i] for i in range(1, 10)]
>>> 
>>> lst_gen
[[1, 1], [2, 4], [3, 9], [4, 16], [5, 25], [6, 36], [7, 49], [8, 64], [9, 81]]
>>> 
>>> [num for elem in lst_gen for num in elem]
[1, 1, 2, 4, 3, 9, 4, 16, 5, 25, 6, 36, 7, 49, 8, 64, 9, 81]

这是我的参考 http://docs.python.org/2/tutorial/datastructures.html

于 2013-05-17T14:34:50.317 回答
1

一个简单的可能是:

[i ** j for i in range(1, 6) for j in [1, 2]]

这对于任务以及列表 comp 替换两个嵌套循环这一事实非常明确(而正如其他答案所示,可以说是可以展平的)。输出:

[1, 1, 2, 4, 3, 9, 4, 16, 5, 25]
于 2021-07-20T09:45:36.130 回答
1

这个线程有很多技巧。这是另一个使用没有进口的单线发电机

x = (lamdba : [[(yield i), (yield i**2)] for i in range(10)])()

编辑:这将引发 Python 3.7 中的 DeprecatedWarning 和 Python 3.8 中的 SyntaxError: https ://docs.python.org/dev/whatsnew/3.7.html#deprecated-python-behavior

于 2018-03-16T12:39:57.550 回答
0

如前所述,itertools是要走的路。这是我的做法,我觉得更清楚:

[i if turn else i*i for i,turn in itertools.product(range(1,10), [True, False])]
于 2016-02-10T10:05:56.417 回答
-1

试试这两个班轮

lst = [[i, i*i] for i in range(10)]
[lst.extend(i) for i in lst]

根据需要更改数学。

更好

#Change my_range to be the number you want range() function of
start = 1
my_range = 10
lst = [i/2 if i % 2 == 0 else ((i-1)/2)**2 for i in range(start *2, my_range*2 - 1)]
于 2015-08-07T10:10:37.140 回答