Removing non-primes numbers from list

你。 提交于 2019-12-23 02:48:35

问题


I've got something like this:

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)

And it doesnt remove all non primes

I can not figure out why


回答1:


In your code:

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

You are modifying (with .remove()) the same list you're iterating over (with in). This is not recommended and you may end up removing different items that you intend.

Instead, consider a list comprehension:

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



回答2:


Your return values for isPrime are the opposite of what they should be.




回答3:


You are iterating through an iterable and simultaneously modifying that iterable. So when one loop is completed, the pointer may not necessarily be pointing to the next item in the original set through which you were iterating.

If isPrime(palindrom) returns True and you remove one item, the length of the list is reduced by one.

Consider a situation where palindromes = [7,8,9,10] and palindrom is having value 8. palindrom is actually pointing to palindromes[1]. After the loop is over, palindrome will be pointing to palindromes[2]. Meanwhile since 8 will be removed from palindromes since it is not a prime. Now palindromes = [7,9,10] and palindrom = palindromes[2] = 10. You can see that the value 9 is never touched.

The moral: Never manipulate the iterable on which you are iterating. It is like cutting the branch of the tree on which you are sitting.

(by the way, the function name should have been isNotPrime rather than isPrime to reflect what it was checking. :) )




回答4:


If you want all the primes that are palindromes, this will work better:

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)]


来源:https://stackoverflow.com/questions/7786566/removing-non-primes-numbers-from-list

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!