【问题标题】:Modify the iterated list of a for loop inside the loop修改循环内for循环的迭代列表
【发布时间】:2015-05-09 21:29:48
【问题描述】:

for 循环遍历一个长列表。我试图加速修改列表的迭代(没有成功)。 代码:

from math import sqrt
def holeofStrainer():
    isPrime = [False, False] + [True]*999999
    for num in range(3, len(isPrime)):
        if isPrime[num] == False:
            continue
        else:
            for x in range(2, int(sqrt(num)) + 1):
                if num % x == 0:
                    isPrime[num] = False        
                    break
            else:          
                isPrime[num] = True       
                for item in range (2, int(1000001/num) + 2):
                    ple = item * num
                    if ple < len(isPrime):
                        isPrime[ple] = False  
    return(isPrime) 
print(holeofStrainer())

第 5 行的目标是省去不必要的计算。

第 14-17 行我做了 修改(按照 Eratosthenes 的筛子,我将素数的倍数的值更改为 False)通过这种方式避免通过第 5 行进行更多计算。

总结:

  1. 是否可以从循环本身修改循环迭代列表?
  2. 如果答案是肯定的,为什么我的代码不好?

【问题讨论】:

  • for item in range (2, int(1000001/num) + 2) 在做什么以及您实际上想用您的代码做什么?
  • @PadraicCunningham “埃拉托色尼筛法”是一种通过过滤掉特定范围内的所有非素数来查找素数的方法。
  • 以后,使用 4 个空格的缩进,因为这真的很难读。
  • for num in isPrime: num 现在是TrueFalse,而不是索引位置。
  • @PadraicCunningham 问题是一团糟,这段代码没有做它应该做的事情 - 而 OP 不是试图让它工作而是试图让它更有效率:)

标签: python list loops iteration self-modifying


【解决方案1】:

我很确定,您偶然发现了一个过早优化的案例,即在没有工作代码的情况下尝试构建快速代码。

你的外部 for 循环

for num in isPrime:

迭代isPrime 中的TrueFalse 值,而不是数字或索引位置。

            for item in range (2, int(1000001/num) + 2):
                ple = item * num
                if ple < len(isPrime):
                    isPrime[ple] = False 

正如 Padraic Cunningham 在 cmets 中所指出的,我不知道这部分代码应该实现什么。还有一个 DRY 违规(重复限制数)。

如果我清理所有这些,我最终会得到类似的东西

def holeofStrainer(nprimes):
    isPrime = [False, False] + [True] * (nprimes - 1)
    for num in (num for num, numIsPrime in enumerate(isPrime) if numIsPrime):                                            
        for x in xrange(2, int(sqrt(num)) + 1):                                                                           
            if num % x == 0:                 
                isPrime[num] = False
                break                      
     return isPrime

注意使用xrange() 而不是range()。如果这是 python 2,range() 在调用时会创建一个完整列表,这对于较大的数字会造成很大的伤害。

holeofStrainer(1000000) 大约需要 14 秒才能跑到这里。这可能可以更快地完成(例如,首先检查和存储奇数),但已经有更快的 SO 工作版本。

【讨论】:

  • 很好。你的回答真是太好了!
  • 很好。你的回答真是太好了!首先在 for 项目中...我试图将值 False 归因于列表中与素数的倍数相对应的每个元素。对我来说,这份清单就像一本字典。这些项目是对问题的布尔响应是素数?,元素的索引是我们询问的关于它的素数。
  • 什么是“numIsPrime”?
  • 很好。你的回答真是太好了!首先在 for 项目中...我试图将值 False 归因于列表中与素数的倍数相对应的每个元素。对我来说,这份清单就像一本字典。这些项目是对问题的布尔响应是素数?,元素的索引是我们询问的关于它的素数。迭代创建了它们对应于列表元素索引的素数的所有倍数。
  • numIsPrimeisPrime 列表中的值 True/False 偏移/位置 num 处的数字。在您的代码中,您使用 False 表示 is provable not prime ,所以我坚持了这一点。列表理解或多或少等同于通过if not isPrime[num] 保护循环的内容。在您的原始代码中,您从未从列表中获得实际位置/编号,只有 True/False 值。
猜你喜欢
  • 2017-08-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多