【问题标题】:I want to take the XOR of all the elements of 1 list with another. How do I do it? [duplicate]我想将 1 个列表的所有元素与另一个进行 XOR。我该怎么做? [复制]
【发布时间】:2019-10-19 06:54:12
【问题描述】:

我有一堆形式为 [0,0,1,0,1...] 的列表,我想对 2 个列表进行 XOR 并将输出作为列表给出。 喜欢: [ 0, 0, 1 ] 异或 [ 0, 1, 0 ] -> [ 0, 1, 1 ]

res = []
tmp = []

for i in Employee_Specific_Vocabulary_Dict['Binary Vector']:
    for j in Course_Specific_Vocabulary_Dict['Binary Vector']:

        tmp = [i[index] ^ j[index] for index in range(len(i))]
        res.append(temp)

我的每个列表/向量的大小约为 3500 个元素,因此我需要一些东西来节省时间,因为这段代码需要 20 多分钟才能运行。

我有 3085 个列表,每个列表都需要与 4089 个其他列表进行异或运算。

如何在不显式遍历每个列表的情况下做到这一点?

【问题讨论】:

  • 你试过什么?你用的代码在哪里?
  • “所以我需要一些东西来节省时间” - 不,你不需要,至少在你做某事并发现它太慢之前不需要。在您尝试之前,甚至很难猜出这样做所花费的时间数量级(是毫秒、微秒、秒还是分钟?)
  • 好的,我将其标记为重复,因为简单的 XOR python 搜索给了我上面的链接。您可以轻松地使用 for 循环或列表推导
  • 无论您选择哪种实现,实现的底层机制都会遍历这两个列表。你无法避免这一点。这是编程的一个基本方面。此外,3500 个元素绝对不算什么。即使是由于所有数组实际上都是哈希图而导致内存效率低下的 PHP,也可以在近乎即时的时间内处理具有 3500 个元素的数组。您没有任何理由担心这里的运行时效率。
  • 实际上我有两组列表:第一组有 3085 个列表,第二组有 4089 个列表,我需要将 3085 个列表中的每一个与 4089 个列表中的每一个进行 XOR。因此运行代码需要很长时间(超过 20 分钟),我想以某种方式对其进行优化

标签: python python-3.x list large-data xor


【解决方案1】:

使用map:

answer = list(map(operator.xor, lst1, lst2)).

zip:

answer = [x ^ y for x,y in zip(lst1, lst2)]

如果您需要更快的速度,请考虑使用 NumPy 而不是 Python 列表来保存您的数据。

【讨论】:

  • 如果我有 numpy 数组而不是列表,您的代码将如何更改?
  • 如果你有 NumPy 数组,你可以简单地写类似answer = arr1 ^ arr2;当参数都是参数时,NumPy 简单地定义了许多二元运算符来执行逐点运算。
  • 但是,根据您的编辑,您不希望逐点操作,而是希望对两个列表的 product 的每个元素执行 XOR,这本质上是O(n^2) 操作。 NumPy 将无法显着加快速度。
【解决方案2】:

假设ab 的大小相同,您可以使用xor 操作(即^)和简单的列表索引:

a = [0, 0, 1]
b = [0, 1, 1]
c = [a[index] ^ b[index] for index in range(len(a))]
print(c) # [0, 1, 0]

或者您可以将zipxor 一起使用:

a = [0, 0, 1]
b = [0, 1, 1]
c = [x ^ y for x, y in zip(a, b)]
print(c) # [0, 1, 0]

zip 只会进入最短的列表(如果它们的大小不同)。如果它们的大小不同,并且您想转到更长的列表,可以使用zip_longest

from itertools import zip_longest
a = [0, 0, 1, 1]
b = [0, 1, 1]
c = [x ^ y for x, y in zip_longest(a, b, fillvalue=0)]
print(c) # [0, 1, 0, 1]

【讨论】:

    【解决方案3】:

    使用numpy应该会有一些性能提升,你需要的函数是bitwise_xor,像这样:

    import numpy as np
    results = []
    for i in Employee_Specific_Vocabulary_Dict['Binary Vector']:
        for j in Course_Specific_Vocabulary_Dict['Binary Vector']:
            results.append(np.bitwise_xor(i, j))
    

    概念证明:

    a = [1,0,0,1,1]
    b = [1,1,0,0,1]
    x = np.bitwise_xor(a,b)
    print("a\tb\tres")
    for i in range(len(a)):
        print("{}\t{}\t{}".format(a[i], b[i], x[i]))
    

    输出:

    a       b       x
    1       1       0                                                                                                       
    0       1       1                                                                                                       
    0       0       0                                                                                                       
    1       0       1                                                                                                       
    1       1       0
    

    编辑

    请注意,如果您的数组大小相同,您只需执行一项操作,bitwise_xor 仍然可以工作,所以:

    a = [[1,1,0], [0,0,1]]
    b = [[0,1,0], [1,0,1]]
    res = np.bitwise_xor(a, b)
    

    仍然可以工作,您将拥有:

    res: [[1, 0, 0], [1, 0, 0]]
    

    在您的情况下,解决方法可能是:

    results = []
    n = len(Course_Specific_Vocabulary_Dict['Binary Vector'])
    for a in Employee_Specific_Vocabulary_Dict['Binary Vector']:
        # Get same size array w.r.t Course_Specific_Vocabulary_Dict["Binary Vector]
        repeated_a = np.repeat([a], n, axis=0)
        results.append(np.bitwise_xor(repeated_a, Course_Specific_Vocabulary_Dict['Binary Vector']))
    

    但是我不知道这是否真的会提高性能,有待检查;肯定会需要更多内存。

    【讨论】:

    • 嗨。在运行您的代码 sn-p 时,我收到以下错误:ValueError: operands could not be broadcast together with shapes (3085,3761) (3085,)
    • sn-ps 我写了哪个代码?另外,您的阵列的形状是什么?我刚刚尝试过它们,它们正在工作。请记住,要执行此类操作,它们需要具有相同的长度。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-14
    • 1970-01-01
    • 2023-04-06
    • 1970-01-01
    • 1970-01-01
    • 2023-02-03
    • 2015-10-17
    相关资源
    最近更新 更多