是否有一种形式的'用于'评估"表达式列表"每次?

时间:2018-03-25 04:56:10

标签: python python-3.x for-loop

lt = 1000 #list primes to ...
remaining = list(range(2, lt + 1)) #remaining primes

for c in remaining: #current "prime" being tested
    for t in remaining[0: remaining.index(c)]: #test divisor
        if c % t == 0 and c != t:
            if c in remaining:
                remaining.remove(c)

如果您不需要上下文:

如何重新运行相同的目标列表值,或者使用除此之外的其他内容在每次迭代时读取表达式列表?

如果您需要上下文:

我目前正在创建一个程序,列出从2到给定值(lt)的素数。我有一个清单'剩下的'从2到给定值的所有整数开始。一次一个,它测试列表中的值' c'并按列表中的所有较小数字逐一检验可分性' t'。如果' c'可以被&t; t'整除,它会从列表中删除它。在程序结束时,从理论上讲,只有素数仍然存在,但我遇到的问题是因为我从列表中删除项目,并且只有读取剩余一次,因为正在跳过剩余的值,因此将复合物留在列表中

2 个答案:

答案 0 :(得分:1)

你要做的几乎从来都不是正确的答案(这里肯定不是正确的答案,原因我稍后会介绍),这就是为什么Python没有给你一个方法来做到这一点自动。事实上,当你迭代它时,删除或插入列表是非法的,即使CPython和其他Python实现通常不检查该错误。

但有一种方法可以模拟你想要的东西,但有点冗长:

for i in range(remaining.index(c)):
    if i >= remaining.index(c): break
    t = remaining[i]

现在我们没有迭代remaining,我们正在迭代它的索引。因此,如果我们删除值,我们将迭代修改列表的索引。 (当然我们并不真正依赖range那里,因为if…break测试同样的事情;如果你更喜欢for i in itertools.count():,那也会有用。)

而且,根据您想要做的事情,您可以通过不同的方式进行扩展,例如:

end = remaining.index(c)
for i in range(end):
    if i >= end: break
    t = remaining[i]
    # possibly subtract from end within the loop
    # so we don't have to recalculate remaining.index(c)

......等等。

然而,正如我在顶部提到的,这真的不是你想要做的。如果你查看你的代码,它不仅会循环遍历所有小于c的素数,它会在该循环中调用一堆函数,循环遍历所有小于{的{ {1}}或您的整个列表(cindexremove适用于列表的方式),这意味着您将线性工作转变为二次方工作。

最简单的方法是停止尝试改变原始列表以删除复合数字,然后在进行时构建一组素数。您可以在固定时间内搜索,添加和删除集合。你可以用显而易见的方式迭代你的列表,因为你不再改变它。

最后,这实际上并没有实现一个适当的素数筛,而是一个效率低得多的算法,由于某些原因,每个人几十年来一直在教授一个Scheme示例,最近翻译成其他语言。有关详细信息,请参阅The Genuine Sieve of Eratosthenes,有关Python和Ruby的示例代码,请参阅this project,其中显示了如何实现适当的筛选以及对性能权衡的一些评论。

答案 1 :(得分:0)

(在下文中,我忽略了使用 a"可变for"找到素数XY problem。)

在修改序列时,在具有明确定义(和有效)行为的序列上设计迭代并非完全无关紧要。在你的情况下,序列只是耗尽,一个合理的做法是使用一个列表但是"删除"通过用特殊值替换它们的元素。 (这样可以很容易地保留当前的迭代位置,并避免转移后续元素的成本。)

为了有效地跳过已删除的元素(对于外部迭代和任何内部迭代,如示例所示),特殊值应该是(或包含)任何后续删除元素的计数。请注意,有一种特殊情况是删除当前元素,为了获得最大效率,您必须移动光标,同时仍然知道要移动多远。