查找两个数组的交集高效算法实现

67 阅读4分钟

给定两个数组 a 和 b,求它们在第一个元素相同的数组元素的第二个元素之和。例如,对于 a = [[125, 1], [193, 1], [288, 23]] 和 b = [[108, 1], [288, 1], [193, 11]],结果为 result = [[288, 24], [193, 12]]。

2. 解决方案

解决方案 1:

da = dict(a)
db = dict(b)

result = [[k, da[k] + db[k]] for k in set(da.keys()).intersection(db.keys())]

此解决方案首先将两个数组转换为字典,然后求出两个字典的交集,再根据交集的键分别求出两个字典中对应键的值之和,最后将结果保存在列表中并返回。

解决方案 2:

result = []
ms, mb = (dict(a), dict(b)) if len(a) < len(b) else (dict(b), dict(a))
for k in ms:
    if k in mb:
        result.append([k, ms[k] + mb[k]])

此解决方案与第一个解决方案类似,不同之处在于它使用了列表推导来生成结果,并使用最小值和最大值两个变量来处理两个数组长度不同的情况。

解决方案 3:

from collections import Counter

c_sum = Counter()
c_len = Counter()
for elt in a:
    c_sum[elt[0]] += elt[1]
    c_len[elt[0]] += 1

for elt in b:
    c_sum[elt[0]] += elt[1]
    c_len[elt[0]] += 1

print([[k, c_sum[k]] for k, v in c_len.iteritems() if v > 1])

此解决方案利用 Counter 类来统计两个数组中的元素个数和元素之和,然后根据元素个数大于 1 的元素来生成结果。Counter 类是一个字典子类,它可以统计字典中元素的个数,并提供一些方便的方法来操作字典。

解决方案 4:

inter = []
for e in a:
    for e2 in b:
        if e[0] == e2[0]:
            inter.append([e[0], e[1] + e2[1]])
print(inter)

此解决方案通过迭代比较两个数组中的元素来找到交集,然后将交集元素的第二个元素之和保存在列表中并返回。

解决方案 5:

from collections import defaultdict

d = defaultdict(int)

for value, num in a + b:
    d[value] += num
result = filter(lambda x: x[1] > 1, d.items())
result = map(list, result)  # If it's important that the result be a list of lists rather than a list of tuples
print(result)

此解决方案使用 defaultdict 类来累加两个数组中的元素之和,然后过滤掉元素之和小于 2 的元素,最后将结果保存在列表中并返回。

解决方案 6:

result = [[ae[0], ae[1] + be[1]] for be in b for ae in a if be[0] == ae[0]]

此解决方案使用列表推导来生成结果,其中 be 和 ae 分别代表两个数组中的元素,if be[0] == ae[0] 用于比较两个元素的第一个元素是否相等。

解决方案 7:

k = {}  # store totals
its = {}  # store intersections
for i in a + b:
    if i[0] in k:
        its[i[0]] = True
        k[i[0]] += i[1]
    else:
        k[i[0]] = i[1]
# then loop through intersections for results
result = [[i, k[i]] for i in its]

此解决方案首先创建两个字典 k 和 its 来存储元素之和和交集元素,然后遍历两个数组中的元素并更新字典,最后循环遍历交集元素并生成结果。

解决方案 8:

from collections import defaultdict

d = defaultdict(list)
for series in a, b:
    for key, value in series:
        d[key].append(value)
result2 = [(key, sum(values)) for key, values in d.iteritems() if len(values) > 1]

此解决方案使用 defaultdict 类来累加两个数组中的元素之和,然后过滤掉元素个数小于 2 的元素,最后将结果保存在列表中并返回。

解决方案 9:

aa = Counter(dict(a))
bb = Counter(dict(b))
cc = aa + bb
print(list(cc.items()))
if you must only include the common keys:
print([(k, cc[k]) for k in set(aa).intersection(bb)])

此解决方案使用 Counter 类来统计两个数组中的元素个数和元素之和,然后相加得到交集元素,最后将结果保存在列表中并返回。

解决方案 10:

import numpy as np

a = np.array([[125, 1], [193, 1], [288, 23]])
b = np.array([[108, 1], [288, 1], [193, 11]])

aS = a.T[0][np.argsort(a.T[0])]
bS = b.T[0][np.argsort(b.T[0])]

i = np.intersect1d(a.T[0], b.T[0])

cT = np.hstack((a.T[:, np.searchsorted(aS, i)], b.T[:, np.searchsorted(bS, i)]))

print([[item, np.sum(cT[1, np.argwhere(cT[0] == item).flatten()])] for item in i])

此解决方案使用 numpy 库中的 serachsorted()、argsort() 和 intersect1d() 函数来找到交集元素,然后根据交集元素的索引来取出两个数组中对应元素的第二个元素之和,最后将结果保存在列表中并返回。

以上就是对这个问题的十种解决方案,你也可以根据自己的需求选择合适的解决方案。