Python列表操作的性能问题

时间:2014-11-23 16:54:11

标签: python performance list

我正在学习python并且有一个练习,其中我有一个整数列表,并且必须保持两个数字,然后是2对3,然后是3对4 ...然后看到剩下的是什么。 例如: [1,2,3,4,5,6,7,8,9] - > [1,3,5,7,9] - > [1,3,7,9] - > [1,3,7]

我的第一次尝试,只是为了看输出(小心,令人震惊的脏代码):

n=input()
list2=list(range(1,int(n))) 
list1=[]
step=2
while list1 != list2 :
    countSteps=1
    position=0
    list1=list2
    list2=[]
    lenlist1=len(list1)
    while position < lenlist1 :
      while countSteps != step and position < lenlist1 :
        list2.append(list1[position])
        countSteps+=1
        position+=1
      position+=1
      countSteps = 1
    step+=1
print(list2)

&#34;想法&#34;有两个列表使用1/2/3 ...添加2/3/4 ...数字从一个到另一个。在我看来(也许我错了)记忆明智这是一个糟糕的选择,所以我想出了以下内容:

n=input()
list1=list(range(1,int(n)))
lenCached=0
step=1
while lenCached!=len(list1) :
  lenCached = len(list1)
  position = step
  while position < len(list1):
    list1.pop(position)
    position+=step
  step+=1
print(list1)

我很高兴这最后一个看起来如何,但表现很可怕。当我运行第一个范围(1,1000000)时,它需要10秒,而第二个需要年龄(几分钟)。 为什么我能做些什么呢?

(如果读到这个,你想到了一个更好的方法来实现最初的目标,我当然会有兴趣听到它!)

1 个答案:

答案 0 :(得分:5)

你的第二个代码慢得多的原因是列表上的pop操作非常慢(它的运行时间与列表的长度成正比而不是常量),如here所述,除非你从列表的末尾弹出一个项目。

这是一个与您的第一个代码具有相似性能的代码(在我的机器上略胜一筹),但看起来更惯用。特别是,我使用的是list comprehension,而不是append用于从l2构建l1的系列n=input() l = list(range(1, n)) step = 2 while step <= len(l): l = [num for ind, num in enumerate(l) if (ind + 1) % step != 0] step += 1 print(l)

import numpy as np

n = input()
a = np.arange(1, n)
step = 2
while step <= len(a):
    mask = np.ones(len(a), dtype=bool)
    ind = np.arange(step-1,len(a), step)
    mask[ind] = False
    a = a[mask]
    step += 1
print(a)

一个非常快的实现:

{{1}}

顺便说一句,此过程称为Flavius Josephus's sieve