判断两个列表是否互为补充的最快方法?

Quickest way to tell if two lists are complements of each other?

我有两个数组:

a = [0,1,0,1,0,1,0,1]
b = [1,0,1,0,1,0,1,0]

确定每个元素是否为另一个元素(补码)的倒数的最快方法是什么?

所以为了使上面的内容显而易见 return True

但对于这些数组:

a = [1,1,0,1,0,1,0,1]
b = [1,0,1,0,1,0,1,0]

会returnFalse

我觉得这个问题已经很清楚了,但是要更详细一点:

您可以压缩列表以比较这些对。为了知道它们是否 'complement' 彼此,因为您的所有值都是 1 或 0,只需检查它们的总和是否为 1:

a = [0,1,0,1,0,1,0,1]
b = [1,0,1,0,1,0,1,0]

all(va + vb == 1 for va, vb in zip(a, b))
# True

a = [1,1,0,1,0,1,0,1]
b = [1,0,1,0,1,0,1,0]

all(va + vb == 1 for va, vb in zip(a, b))
# False

请注意,将 all 与生成器表达式一起使用只会检查需要决定的内容,一旦遇到无效的对,它将立即停止。

更新 2

如果数字只有1或0,您可以通过简单比较来测试补码。这比测试总和快了大约 15%:

complement = all(False for aa , bb in zip(a, b) if aa == bb)

更新

根据评论,我做了一些时间测试。在使用 all

测试列表之前过滤列表确实更快(大约 20%)
complement = all(False for aa, bb in zip(a, b) if aa ^ bb != 1)

奇怪的是:

complement = all(False for va, vb in zip(a, b) if va + vb != 1)

又快了大约 10%。这对我来说没有任何意义,因为加法是比按位异或复杂得多的操作。

原回答

您可以使用按位 xor 来确定值是否互补。

a = [0,1,0,1,0,1,0,1]
b = [1,0,1,0,1,0,1,0]

complement = all(aa ^ bb == 1 for aa , bb in zip(a, b))
print(complement)
# True

a = [1,1,0,1,0,1,0,1]
b = [1,0,1,0,1,0,1,0]

complement = all(aa ^ bb == 1 for aa , bb in zip(a, b))
print(complement)
# False

如果它们是 01 以外的值,这也可以通过与 2^n-1 比较来实现,其中 n 是值:

a = [3, 2, 1, 0]
b = [0, 1, 2, 3]

complement = all(aa ^ bb == 3 for aa , bb in zip(a, b))
print(complement)
# True

你可以用一个简单的 for 循环来做到这一点:

def is_complement(a, b):
    for i in range(len(a)):
        if a[i] == b[i]:
            return False
    return True

可以使用operator.xor to do bitwise XOR along with zip to zip the two lists together and all来检查是否所有的对都是互补的或者return 1:

>>> import operator
>>> a = [0,1,0,1,0,1,0,1]
>>> b = [1,0,1,0,1,0,1,0]
>>> all(operator.xor(x, y) for x, y in zip(a, b))
True
>>> a = [1,1,0,1,0,1,0,1]
>>> b = [1,0,1,0,1,0,1,0]
>>> all(operator.xor(x, y) for x, y in zip(a, b))
False