Python:创建n个列表列表的最快方法

时间:2011-04-01 20:24:00

标签: python

所以我想知道如何最好地创建一个空白列表列表:

[[],[],[]...]

由于Python如何使用内存中的列表,这不起作用:

[[]]*n

这会创建[[],[],...],但每个元素都是相同的列表:

d = [[]]*n
d[0].append(1)
#[[1],[1],...]

像列表理解这样的东西:

d = [[] for x in xrange(0,n)]

但这会使用Python VM进行循环。有没有办法使用隐含循环(利用它用C语言编写)?

d = []
map(lambda n: d.append([]),xrange(0,10))

这实际上比较慢。 :(

4 个答案:

答案 0 :(得分:86)

可能只是比

快一点的方法
d = [[] for x in xrange(n)]

from itertools import repeat
d = [[] for i in repeat(None, n)]

它不必在每次迭代中创建一个新的int对象,并且在我的机器上快5%。

编辑:使用NumPy,您可以使用

来避免Python循环
d = numpy.empty((n, 0)).tolist()

但这实际上比列表理解慢2.5倍。

答案 1 :(得分:12)

列表推导实际上比显式循环更有效地实现(参见the dis output for example functions),并且map方法必须在每次迭代时调用ophaque可调用对象,这会产生相当大的开销。

无论如何,[[] for _dummy in xrange(n)]是正确的方法,并且的各种其他方式之间的微小(如果存在)速度差异都不应该重要。当然,除非您花费大部分时间来做这件事 - 但在这种情况下,您应该使用算法。你多久创建一次这些列表?

答案 2 :(得分:10)

以下是两种方法,一种是甜的和简单的(和概念的),另一种是更正式的,可以在阅读数据集之后在各种情况下进行扩展。

方法1:概念

X2=[]
X1=[1,2,3]
X2.append(X1)
X3=[4,5,6]
X2.append(X3)
X2 thus has [[1,2,3],[4,5,6]] ie a list of lists. 

方法2:正式和可扩展的

将列表存储为不同数字列表列表的另一种优雅方式 - 它从文件中读取。 (此处的文件包含数据集列表) Train是一个数据集,例如50行和20列。即。 Train [0]给我第一行的csv文件,train [1]给我第二行,依此类推。我有兴趣将数据集与50行分离为一个列表,除了列0,这是我在这里解释的变量,因此必须从orignal train数据集中删除,然后在列表后按比例放大列表 - 即列表列表。这是执行此操作的代码。

请注意,我在内循环中读取“1”,因为我只对解释变量感兴趣。我在另一个循环中重新初始化X1 = [],否则X2.append([0:(len(train [0]) - 1)])会一遍又一遍地重写X1 - 除了它更有效的内存。

X2=[]
for j in range(0,len(train)):
    X1=[]
    for k in range(1,len(train[0])):
        txt2=train[j][k]
        X1.append(txt2)
    X2.append(X1[0:(len(train[0])-1)])

答案 3 :(得分:1)

所以我做了一些速度比较以获得最快的方式。 列表推导确实非常快。接近的唯一方法是避免在构造列表期间字节码被执行。 我的第一次尝试是以下方法,原则上似乎更快:

l = [[]]
for _ in range(n): l.extend(map(list,l))

(产生一个长度为2 ** n的列表,当然) 根据timeit,对于短期和长期(百万)列表,这种构造的速度是列表理解的两倍。

我的第二次尝试是使用starmap为我调用列表构造函数,有一个构造,它似乎以最高速度运行列表构造函数,但仍然较慢,但只是很少量:

from itertools import starmap
l = list(starmap(list,[()]*(1<<n)))

有趣的是,执行时间表明最终的列表调用使得starmap解决方案变慢,因为它的执行时间几乎完全等于以下的速度:

l = list([] for _ in range(1<<n))

当我意识到列表(())也产生了一个列表时,我的第三次尝试就来了,所以我尝试了这个简单明了:

l = list(map(list, [()]*(1<<n)))

但这比星图呼叫慢。

结论:对于速度疯子: 请使用列表理解。 如果必须,只调用函数。 使用内置。