问题
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