我想创建一系列长度不同的列表。每个列表将包含相同的元素e,重复n次(其中n =列表的长度)。

我如何创建列表,而不使用列表理解[e为xrange(n)中的数字]为每个列表?


当前回答

如果你在寻找

[1, 1, 1, 2, 2, 2, 3, 3, 3]

如果没有numpy,可以使用内置的itertools模块

from itertools import chain
list(chain.from_iterable(zip(*[[1,2,3]]*3)))

使用简单的列表推导式(甚至没有itertools)

[e for x in zip(*[[1,2,3]]*3) for e in x]

其他回答

你也可以这样写:

[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。

[e] * n

应该工作

正如其他人指出的那样,对可变对象使用*操作符会重复引用,所以如果你改变了一个,你就改变了所有引用。如果想要创建可变对象的独立实例,xrange语法是最python化的方法。如果您对从未使用过的命名变量感到烦恼,则可以使用匿名下划线变量。

[e for _ in xrange(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)

在Python中创建单个项目重复n次的列表

根据您的用例,您希望使用具有不同语义的不同技术。

将列表中的不可变项相乘

对于不可变项,如None、bool、int、float、字符串、元组或frozensets,你可以这样做:

[e] * 4

注意,这通常只用于列表中的不可变项(字符串、元组、frozensets),因为它们都指向内存中相同位置的相同项。当我必须构建一个包含所有字符串的模式的表时,我经常使用这个方法,这样我就不必给出一个高度冗余的一对一映射。

schema = ['string'] * len(columns)

在我们想重复同一项的地方乘以列表

将列表相乘会得到相同的元素。这种需求很少见:

[iter(iterable)] * 4

这有时用于将一个iterable映射到一个列表的列表:

>>> 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四次包含相同的range迭代器:

>>> a_list
[<range_iterator object at 0x7fde73a5da20>, <range_iterator object at 0x7fde73a5da20>, <range_iterator object at 0x7fde73a5da20>, <range_iterator object at 0x7fde73a5da20>]

可变的物品

我已经使用Python很长一段时间了,我很少看到用可变对象执行上述操作的用例。

相反,要获得一个可变的空列表、set或dict,你应该这样做:

list_of_lists = [[] for _ in columns]

在这个上下文中,下划线只是一个随意使用的变量名。

如果你只有数字,那将是:

list_of_lists = [[] for _ in range(4)]

_并不是特别的,但是如果你不打算使用这个变量而使用任何其他名称,你的编码环境风格检查器可能会抱怨。


对可变项使用immutable方法的注意事项:

小心对可变对象这样做,当你改变其中一个对象时,它们都会改变,因为它们都是相同的对象:

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