[英]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.