从多个数组列表中查找公共值的更有效方法

问题描述 投票:0回答:2

我想找到一种更有效的方法从一组数组中查找共同值。假设我有三个数组列表:

list_1 = [np.array([1, 2, 3]), np.array([]), np.array([4, 5, 6])]
list_2 = [np.array([2, 3, 6], np.array([1, 2, 3]), np.array([4, 5, 6, 7, 8, 9])]
list_3 = [np.array([5, 2, 3, 7]), np.array([7, 8, 9]), np.array([1, 2, 3, 4, 5, 6])]

我想要得到的是每个索引中公共元素数组的另一个列表:

out = [np.array([2, 3]), np.array([]), np.array([4, 5, 6])]

目前我正在使用:

common_vals = []
for index in range(len(list_1)):
    common_elements = reduce(np.intersect1d, (list_1[index], list_2[index], list_3[index])
    common_vals.append(common_elements)

当list_1的长度可以是几千个项目并且列表的数量很大时,这非常慢。

可以通过以下方式创建测试集:

from random import random

list_1, list_2, list_3 = [], [], []
for i in range(10_000):
    length_1 = random.randint(0, 1000)
    list_1.append(np.array([random.randint(0,1000) for _ in range(length_1)]))
    length_2 = random.randint(0, 1000)
    list_2.append(np.array([random.randint(0,1000) for _ in range(length_2)]))
    length_3 = random.randint(0, 1000)
    list_3.append(np.array([random.randint(0,1000) for _ in range(length_3)]))

[澄清]

数组列表是索引列表,因此数字始终是整数。它们是有序的并且需要保持该顺序并且将始终具有相同的长度。因此,公共项输出的第一个列表应该是每个输入列表的索引 1 中的公共项。输入列表中的每个项目都是唯一的,因此在最终输出列表中它们应该出现一次。

python arrays numpy
2个回答
3
投票

我怀疑 numpy 在这里会有多大帮助。在我看来,最简单的方法是使用 Python 的集合。转置列表列表以获得列列表,将每列的元素转换为集合,并对它们运行

set.intersection

lists = [list_1, list_2, list_3]
intersections = [set.intersection(*[set(x) for x in col]) for col in zip(*lists)]
print(intersections)
# => [{2, 3}, set(), {4, 5, 6}]

2
投票

使用

set
intersection
怎么样?:

[set.intersection(*map(set, x)) for x in zip(list_1, list_2, list_3)]

输出:

[{2, 3}, set(), {4, 5, 6}]

时间

(使用更大的测试集)

# numpy
1.92 s ± 113 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

# set intersection
801 ms ± 104 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

有序交集

我从您的一条评论中意识到您希望保留商品的原始顺序。

您可以调整上面的代码以首先获取一组,然后使用它来过滤其中一个列表(例如第一个):

def ordered_intersection(it):
    S = set.intersection(*map(set, it))
    return [x for x in it[0] if x in S]

out = [ordered_intersection(x) for x in zip(list_1, list_2, list_3)]

输出:

[[2, 3], [], [4, 5, 6]]
© www.soinside.com 2019 - 2024. All rights reserved.