Idea for key parameter in all() builting, would it be feasible?

Russel Walker russ.pobox at gmail.com
Thu Jun 20 06:05:29 EDT 2013


> If you're getting this via the mailing list, just hit Reply, and then
> 
> change the To: address to python-list at python.org - that's the simplest
> 
> (assuming you don't have a Reply To List feature, but you wouldn't be
> 
> saying the above if you had one). That way, you get a citation line,
> 
> quoted text is marked, and it's taken a minimum of effort.

I guess it was pretty late last night but I didn't notice the huge post reply button *palmface*.

> Awesome! Hey, if you *can* switch to Py3, do try to. It has heaps of
> 
> improvements, and it has a future. :)
> 
> 
> 
> ChrisA

Also I realized that aside from using map or the better alternative imap, an even better way to go might be a generator expression. Completely forgot about those.

So with a slightly less trivial example than the first

>>> all(map(lambda x: n%x, xrange(2, n)))

could be better written as

>>> all(n%x for n in xrange(2, n))

which is roughly 10 times faster and memory efficient, plus syntax is cleaner.
And roughly 1.5 times faster than imap which isn't much but prevents having to import itertools.

But I discovered a new itertools tool and my sieve was successful.

def primeset(upper):
    return set([2]+range(3,upper,2)).difference(set.union(*[set(xrange(p+p,upper,p)) for p in [n for n in xrange(3,int(pow(upper, 0.5)+1)) if all(n%x for x in xrange(2, int(pow(n, 0.5)+1)))]]))

Here is the more sane version of the one-liner above.

def primeset(upper):
    def isprime(n):
        # brute force trial division
        for d in xrange(2, int(pow(n, 0.5)+1)):
            if n%d == 0: return False
        return True
    # Initial set of only odd numbers except for 2
    numbers = set([2]+range(3, upper, 2))
    # List of prime numbers up to square root of upper using brute force.
    primes = [n for n in xrange(2, int(pow(upper,0.5)+1)) if isprime(n)]
    # Multiples of all the prime numbers in the list above.
    all_multiples = (set(xrange(p+p,upper,p)) for p in primes)
    # This was allot faster than reduce(set.union, all_multiples)
    multiples = set.union(*all_multiples)
    # And the sieving action.
    return numbers.difference(multiples)


Rough benchmarks:

>>> timer(primeset, 10**6)
1.0981476384030202

>>> # straight forward Eratosthenes sieve
>>> timer(primes, 10**6)
0.5887037628822327




More information about the Python-list mailing list