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'整除,它会从列表中删除它。在程序结束时,从理论上讲,只有素数仍然存在,但我遇到的问题是因为我从列表中删除项目,并且只有读取剩余一次,因为正在跳过剩余的值,因此将复合物留在列表中
答案 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}}或您的整个列表(c
,index
和remove
适用于列表的方式),这意味着您将线性工作转变为二次方工作。
最简单的方法是停止尝试改变原始列表以删除复合数字,然后在进行时构建一组素数。您可以在固定时间内搜索,添加和删除集合。你可以用显而易见的方式迭代你的列表,因为你不再改变它。
最后,这实际上并没有实现一个适当的素数筛,而是一个效率低得多的算法,由于某些原因,每个人几十年来一直在教授一个Scheme示例,最近翻译成其他语言。有关详细信息,请参阅The Genuine Sieve of Eratosthenes,有关Python和Ruby的示例代码,请参阅this project,其中显示了如何实现适当的筛选以及对性能权衡的一些评论。
答案 1 :(得分:0)
(在下文中,我忽略了使用 a"可变for
"找到素数的XY problem。)
在修改序列时,在具有明确定义(和有效)行为的序列上设计迭代并非完全无关紧要。在你的情况下,序列只是耗尽,一个合理的做法是使用一个列表但是"删除"通过用特殊值替换它们的元素。 (这样可以很容易地保留当前的迭代位置,并避免转移后续元素的成本。)
为了有效地跳过已删除的元素(对于外部迭代和任何内部迭代,如示例所示),特殊值应该是(或包含)任何后续删除元素的计数。请注意,有一种特殊情况是删除当前元素,为了获得最大效率,您必须移动光标,同时仍然知道要移动多远。