简体   繁体   English

使用Map-Reduce时Python中的惰性布尔评估

[英]Lazy boolean evaluation in Python when using Map-Reduce

I will use my example: I want to create a list of primes using the sieve of Eratosthenes. 我将使用我的示例:我想使用Eratosthenes筛子创建一个素数列表。 For each number, I check if it is composite, and if not, I append it to the list. 对于每个数字,我都会检查它是否为合成数字,如果不是,则将其附加到列表中。

  • Using "standard" programming: 使用“标准”编程:

     primes = [2] start = time.time() for i in xrange(3,primeRange,2): isPrime = True for p in primes: if(i % p == 0): isPrime = False break; if(isPrime): primes.append(i) print "Using C++-style: ", time.time() - start, " seconds" 
  • Using reduce function: 使用reduce功能:

     start = time.time() for i in xrange(3,primeRange,2): if(reduce(lambda x,y:x and y,[i % p != 0 for p in primes])): primes.append(i) print "Using map-reduce: ", time.time() - start, " seconds" 

The results for primeRange = 100000 : primeRange = 100000的结果:

Using map-reduce:  54.1150000095  seconds
Using C++-style:  4.62000012398  seconds

The 2nd case makes the code more compact, but the condition will be evaluated for the entire list and then reduced to True / False . 第二种情况使代码更加紧凑,但是条件将针对整个列表进行评估,然后减少为True / False Is there a way to avoid that? 有办法避免这种情况吗?

You could use all with a generator expression: 您可以将all与生成器表达式一起使用:

if all(i % p != 0 for p in primes)

The generator expression will lazily evaluate one term at a time, and all will return early if it hits a value that doesn't satisfy the condition. 生成器表达式每次将懒惰地求值一个项,如果表达式的值不满足条件,则all表达式将早返回。

yes, you should do two things. 是的,您应该做两件事。

First, if you want to avoid fully evaluating a list comprehension, don't use a list comprehension, use a generator expression: 首先,如果要避免完全评估列表理解,请不要使用列表理解,请使用生成器表达式:

... [i % p != 0 for p in primes] ...

should be 应该

... (i % p != 0 for p in primes) ...

second, reduce() doesn't understand that lambda x,y:x and y can fail, and there's no way to teach it that. 其次, reduce()无法理解lambda x,y:x and y会失败,并且没有办法教它。 But that doesn't matter, because python has a builtin function for exactly the fold over the conjunction monoid, all() , so the if should be 但这没关系,因为python具有一个内建函数,用于精确地覆盖合取半分词all() ,因此if应该是

if all(i % p != 0 for p in primes):

Use generator, 使用发电机,

def prime_iter(sz):
    '''
    Iterate through all the prime number in range [2,sz]
    '''
    bucket = [0]*sz
    for i in range(2,sz):
        if bucket[i]:
            continue
        for j in range(i+i,sz,i):
            bucket[j] = i
        yield i

# get all the primes from 2 to 100.
primes = list(prime_iter(100))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM