从列表中删除非素数

时间:2011-10-16 19:01:22

标签: python primes

我有这样的事情:

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 个答案:

答案 0 :(得分:10)

在您的代码中:

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

您正在修改(使用.remove())您正在迭代的相同列表(使用in)。不建议这样做,您最终可能会删除您想要的不同项目。

相反,请考虑列表理解

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

答案 1 :(得分:4)

isPrime的返回值与它们应该是的相反。

答案 2 :(得分:2)

您正在迭代迭代并同时修改该可迭代。因此,当一个循环完成时,指针可能不一定指向您正在迭代的原始集合中的下一个项目。

如果isPrime(palindrom)返回True并且您删除了一个项目,则列表的长度减少一个。

考虑一个情况,其中回文数= [7,8,9,10],而回文数值为8。 palindrom实际上指的是回文[1]。循环结束后,回文将指向回文[2]。 同时,由于它不是素数,因此将从回文中删除8。 现在palindromes = [7,9,10]和palindrom = palindromes [2] = 10.你可以看到值9永远不会被触及。

道德:永远不要操纵你迭代的迭代。这就像切割你所坐的树枝。

(顺便说一句,函数名称应该是isNotPrime而不是isPrime来反映它正在检查的内容。:))

答案 3 :(得分:0)

如果你想要所有的回文质数,这将更好:

def eras(n):
    last = n + 1
    sieve = [0,0] + list(range(2,last))
    sqn = int(round(n ** 0.5))
    it = (i for i in xrange(2, sqn + 1) if sieve[i])
    for i in it:
        sieve[i*i:last:i] = [0] * (n//i - i + 1)
    return filter(None, sieve)

def is_palindrome(n):
    ns = str(n)
    ns_reversed = ''.join(reversed(ns))
    return ns == ns_reversed

if __name__ == '__main__':
    primes = eras(100 * 1000)
    print [p for p in primes if is_palindrome(p)]