我有一个数字列表。我想计算列表某些子集的按位 和 。我使用了 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 ] )
但经过大量调试后,我发现它们没有。我不明白背后的原因。
请您参考如下方法:
您误解了 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生成0x因此设置为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]
