从列表中移除非素数数值

1 投票
4 回答
3385 浏览
提问于 2025-04-17 04:26

我有这样的代码:

palindromes=[1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 101, 111, 121, ..., 99799, 99899, 99999]
# of course im generating it :)

def isPrime(number):
    for i in range(2,int(number/2)+1):
        if number%i == 0:
            return True
    return False

def removeNonPrimes(palindromes):
    for palindrom in palindromes:
        if isPrime(palindrom):
            palindromes.remove(palindrom)
    return palindromes

palindromes = removeNonPrimes(palindromes)

但是它没有把所有的非质数都去掉。

我搞不清楚为什么会这样。

4 个回答

2

你在遍历一个可遍历的对象(比如列表)时,同时又在修改这个对象。所以当一个循环结束后,指针可能并不指向你原本正在遍历的下一个项目。

如果函数isPrime(palindrom)返回True,而你又删除了一个项目,那么列表的长度就会减少一个。

想象一下,如果palindromes = [7,8,9,10],而palindrom的值是8。palindrom实际上指向的是palindromes[1]。当循环结束后,palindrom会指向palindromes[2]。与此同时,由于8不是质数,它会被从palindromes中删除。现在palindromes变成了[7,9,10],而palindrom = palindromes[2] = 10。你可以看到,值为9的项目根本没有被处理。

这个教训是:在遍历一个对象时,千万不要对它进行修改。这就像是你坐在树上,却去砍那棵树的树枝。

(顺便说一下,函数的名字应该是isNotPrime,而不是isPrime,这样更能反映它在检查什么。:))

4

你在isPrime这个函数里的返回值跟应该返回的正好相反。

11

在你的代码中:

def removeNonPrimes(palindromes):
    for palindrom in palindromes:
        if isPrime(palindrom):
            palindromes.remove(palindrom)
    return palindromes

你在遍历一个列表的时候,同时又在修改这个列表(用的是.remove())。这样做是不太推荐的,因为你可能会意外地删除一些你不想删除的东西。

相反,你可以考虑使用一种叫做列表推导式的方法:

def removeNonPrimes(palindromes):
    return [p for p in palindromes if isPrime(p)]

撰写回答