只获取一个数组中存在于另一个数组中的元素



我正在学习来自Python的Julia。我想要得到数组b的元素使得每个元素都在数组a中。我在朱莉娅的尝试是在做我需要在python后显示。我的问题是:在Julia中是否有更好/更快的方法来做到这一点?我怀疑我用Julia写的东西的简单性,我担心这样一个看起来幼稚的解决方案可能会有次优的性能(同样来自Python)。

Python:

import numpy as np
a = np.array([1, 2, 3, 4])
b = np.array([7, 8, 2, 3, 5])
indices_b_in_a = np.nonzero(np.isin(b, a))
b_in_a = b[indices_b_in_a]
# array([2, 3])

朱莉娅:

a = [1, 2, 3, 4];
b = [7, 8, 2, 3, 5];
indices_b_in_a = findall(ele -> ele in a, b);
b_in_a = b[indices_b_in_a];
#2-element Vector{Int64}:
# 2
# 3

也许这将是一个有用的答案:

julia> intersect(Set(a), Set(b))
Set{Int64} with 2 elements:
2
3
# Or even
julia> intersect(a, b)
2-element Vector{Int64}:
2
3

注意,如果你有重复的数字,这个方法不能完全复制你的预期行为,因为我在这里工作的唯一值!如果您有重复的元素,那么应该替换为逐个元素的搜索方法!在这种情况下,使用二进制搜索是个不错的选择。
另一种方法是在Julia中使用广播:

julia> a = rand(1:100, 1000);
b = rand(1:3000, 5000);
julia> b[in.(b, Ref(a))]
161-element Vector{Int64}:
8
5
70
73
⋮
# Exactly the same approach with a slightly different syntax
julia> b[b.∈Ref(a)]
161-element Vector{Int64}:
8
5
70
73
30
63
73
⋮

问:Ref在上述代码块中的作用是什么?
答:通过将a包装在Ref中,我对a进行了Ref的引用,并防止编译器在广播过程中迭代a。否则,它将尝试同时迭代ab的元素,这不是正确的解决方案(即使两个对象保持相同的长度)。
然而,Julia的语法是特定的(通常),但它并没有那么复杂。我这么说是因为你提到:

我担心这样一个天真的解决方案…

最后但并非最不重要的是,如果你想在Julia中获得良好的性能,不要忘记将代码包装在函数中。

另一种使用数组推导式的方法。

julia> [i for i in a for j in b if i == j]
2-element Vector{Int64}:
2
3

最新更新