我有一个数字列表。我想计算列表的某个子集的按位and
。我使用了reduce
方法。我认为这两种方法应该产生相同的结果。
table = [5, 10, 2, 6, 7, 18, 19, 1, 4, 9, 17, 8, 16, 0, 15, 11, 12, 13, 3, 14]
l = [0,1,2,3]
print reduce (lambda x,y:table[x]&table[y] , l )
print reduce (lambda x,y:x&y , [ table[x] for x in l ] )
但经过大量调试后我发现他们没有。我不明白背后的原因。
答案 0 :(得分:3)
你误解了reduce()
的作用。它使用前一次调用的结果调用lambda
,并从列表中调用下一个值。如果没有先前的值,则使用列表的第一个元素。
因此,x
每次都会成为以前的结果,除了第一次。 不将从列表推导中变为table[x]
,在不使用列表推导时也不会是列表中的值。
对于您的第一次reduce()
电话,会发生这种情况:
x
设置为0
,y
设置为1
。计算table[0] & table[1]
,结果为5 & 10
,结果为0
。
x
因此设置为0
(之前的结果),y
设置为l
中的下一个值,因此2
。计算table[0] & table[2]
,5 & 2
,结果再次为0
。
x
因此设置为0
(之前的结果),y
设置为l
中的下一个值,因此3
。 table[0] & table[3]
计算得出5 & 6
,结果现在为4
。
您的第二次reduce()
来电直接来自table
,因此您现在使用[5, 10, 2, 6]
作为输入,在缩小时不再咨询table
:
x
设为5
,y
设为10
。 5 & 10
0
x
因此设置为0
(之前的结果),y
设置为列表中的下一个值,因此2
。计算0 & 2
,结果再次为0
。
x
因此设置为0
(之前的结果),y
设置为列表中的下一个值,因此6
。计算0 & 6
,结果再次为0
。
不同之处在于你误解了选择的table[x]
值。
由于reduce()
每次都会将调用应用于上一个结果,因此您应该将其视为一组链式调用。您的第一个reduce()
可以写到:
table[table[table[0] & table[1]] & table[2]] & table[3]
,而您的第二个reduce()
有效地计算:
((table[0] & table[1]) & table[2]) & table[3]
答案 1 :(得分:3)
理解reduce()的最简单方法是查看其纯Python等效代码:
def myreduce(func, iterable, start=None):
it = iter(iterable)
if start is None:
try:
start = next(it)
except StopIteration:
raise TypeError('reduce() of empty sequence with no initial value')
accum_value = start
for x in iterable:
accum_value = func(accum_value, x)
return accum_value
你可以看到,只有你的reduce_func()才能将factorial应用到最右边的参数:
def fact(n):
if n == 0 or n == 1:
return 1
return fact(n-1) * n
def reduce_func(x,y):
return x * fact(y)
lst = [1, 3, 1]
print reduce(reduce_func, lst)