我想创建一系列长度不同的列表。每个列表将包含相同的元素e
,重复n
次数(其中n
= 列表的长度)。
如何创建列表,而不[e for number in xrange(n)]
对每个列表使用列表推导?
我想创建一系列长度不同的列表。每个列表将包含相同的元素e
,重复n
次数(其中n
= 列表的长度)。
如何创建列表,而不[e for number in xrange(n)]
对每个列表使用列表推导?
你也可以写:
[e] * n
您应该注意,例如,如果 e 是一个空列表,您会得到一个包含 n 个对同一列表的引用的列表,而不是 n 个独立的空列表。
性能测试
乍一看,repeat似乎是创建具有 n 个相同元素的列表的最快方法:
>>> timeit.timeit('itertools.repeat(0, 10)', 'import itertools', number = 1000000)
0.37095273281943264
>>> timeit.timeit('[0] * 10', 'import itertools', number = 1000000)
0.5577236771712819
但是等等 - 这不是一个公平的测试......
>>> itertools.repeat(0, 10)
repeat(0, 10) # Not a list!!!
该函数itertools.repeat
实际上并不创建列表,它只是创建一个对象,如果您愿意,可以使用它来创建一个列表!让我们再试一次,但转换为列表:
>>> timeit.timeit('list(itertools.repeat(0, 10))', 'import itertools', number = 1000000)
1.7508119747063233
因此,如果您想要一个列表,请使用[e] * n
. 如果要延迟生成元素,请使用repeat
.
>>> [5] * 4
[5, 5, 5, 5]
当重复的项目是一个列表时要小心。该列表不会被克隆:所有元素都将引用同一个列表!
>>> x=[5]
>>> y=[x] * 4
>>> y
[[5], [5], [5], [5]]
>>> y[0][0] = 6
>>> y
[[6], [6], [6], [6]]
在 Python 中创建重复 n 次的单项列表
根据您的用例,您希望使用具有不同语义的不同技术。
对于不可变项,例如 None、bools、ints、floats、strings、tuples 或 freezesets,您可以这样做:
[e] * 4
请注意,这通常仅与列表中的不可变项(字符串、元组、冻结集)一起使用,因为它们都指向内存中同一位置的同一项。当我必须构建一个包含所有字符串的模式的表时,我经常使用它,这样我就不必提供高度冗余的一对一映射。
schema = ['string'] * len(columns)
将列表相乘一遍又一遍地为我们提供相同的元素。这种需求很少见:
[iter(iterable)] * 4
这有时用于将可迭代对象映射到列表列表中:
>>> iterable = range(12)
>>> a_list = [iter(iterable)] * 4
>>> [[next(l) for l in a_list] for i in range(3)]
[[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]]
我们可以看到a_list
4 次包含相同的范围迭代器:
>>> a_list
[<range_iterator object at 0x7fde73a5da20>, <range_iterator object at 0x7fde73a5da20>, <range_iterator object at 0x7fde73a5da20>, <range_iterator object at 0x7fde73a5da20>]
我已经使用 Python 很长时间了,而且我看到的用例很少,我会使用可变对象执行上述操作。
相反,要获取一个可变的空列表、集合或字典,您应该执行以下操作:
list_of_lists = [[] for _ in columns]
在这种情况下,下划线只是一个一次性变量名。
如果您只有数字,那将是:
list_of_lists = [[] for _ in range(4)]
这_
并不是很特别,但是如果您不打算使用该变量并使用任何其他名称,您的编码环境样式检查器可能会抱怨。
请注意对可变对象执行此操作,当您更改其中一个对象时,它们都会更改,因为它们都是同一个对象:
foo = [[]] * 4
foo[0].append('x')
foo 现在返回:
[['x'], ['x'], ['x'], ['x']]
但是对于不可变对象,您可以使其工作,因为您更改了引用,而不是对象:
>>> l = [0] * 4
>>> l[0] += 1
>>> l
[1, 0, 0, 0]
>>> l = [frozenset()] * 4
>>> l[0] |= set('abc')
>>> l
[frozenset(['a', 'c', 'b']), frozenset([]), frozenset([]), frozenset([])]
但同样,可变对象对此没有好处,因为就地操作会更改对象,而不是引用:
l = [set()] * 4
>>> l[0] |= set('abc')
>>> l
[set(['a', 'c', 'b']), set(['a', 'c', 'b']), set(['a', 'c', 'b']), set(['a', 'c', 'b'])]
Itertools 有一个功能:
import itertools
it = itertools.repeat(e,n)
当然itertools
给你一个迭代器而不是一个列表。[e] * n
给你一个列表,但是,取决于你将如何处理这些序列,这个itertools
变体可能会更有效率。
正如其他人指出的那样,对可变对象使用 * 运算符会重复引用,因此如果您更改一个,则将它们全部更改。如果你想创建一个可变对象的独立实例,你的 xrange 语法是最 Pythonic 的方法。如果您对从未使用过的命名变量感到困扰,您可以使用匿名下划线变量。
[e for _ in xrange(n)]
[e] * n
应该管用
如果您正在寻找一个简单的重复,例如:
[1, 2, 3, 1, 2, 3, 1, 2, 3]
只需使用:
[1, 2, 3] * 3
但是,如果您正在寻找:
[1, 1, 1, 2, 2, 2, 3, 3, 3]
这个更好,但需要更多时间:
numpy.concatenate([([i]*3) for i in [1,2,3]], axis=0)
很抱歉我的回答太晚了您可以numpy.repeat
轻松使用。只需写下您想要产生的值和重复次数。
import numpy as np
x = [1,2,3]
y = np.linspace(0,1000,10000)
for i in x:
new_x = np.repeat(i,len(y))
print(new_x)