根据另一个数组中的搜索,找到数组中元素的索引

26

假设我有两个数组:

a = [1, 2, 5, 7, 6, 9, 8, 3, 4, 7, 0];

b = [5, 9, 6];

我想在a中找到b的值的索引(只找第一次出现的):

c = [3, 6, 5];

有没有一种简单的 Matlab 原生方法可以在不使用循环和搜索的情况下完成这个任务。

我尝试了使用 find() 函数:

find(a == b)

如果你这样做,它会起作用:

for i = 1:length(b)
    index = find(a == b(i));
    c = [c, index(1)]
end

但是更简单的方法会更理想。


MATLAB 使用基于 1 的索引,因此在您的循环解决方案中应该读取 index(1) - Amro
@Amro,哈哈,将近两年后我才看到你的评论。已修复。 - Fantastic Mr Fox
8个回答

20
你可以使用arrayfun将for循环简化为一个简单的一行代码:
arrayfun(@(x) find(a == x,1,'first'), b )

对于更新的Matlab版本(>R2012b),也可以参考Scenia的答案


arrayfun并不比for循环更快。 - niceman
@niceman 我从未说过它是...而且我相信在某些情况下,当JIT启动时(特别是在多核设置上),它将会同样快或更快。另一方面,有些人只喜欢arrayfun的单行功能。对于这个问题,实际上并不重要,因为你最好使用Scenia的答案 - Gunther Struyf

18

事实上,这个功能已经被内置到ismember中。您只需要设置正确的标志,然后它就可以成为一行代码,而且不需要使用arrayfun。版本新于R2012b默认使用此行为。

最初,如果有多个匹配项,ismember会返回最后一个匹配项,R2012a标志使其返回第一个匹配项。

以下是我的测试结果:

a = [1, 2, 5, 7, 6, 9, 8, 3, 4, 7, 0, 6];
b = [5, 9, 6];

[~,c] = ismember(b,a,'R2012a');
>> c
c =
     3     6     5

5

这是对ismember方法的修复,来自@Pursuit的建议。这种方式可以处理一个数字的多个出现,并以正确的顺序返回结果:

[tf,loc] = ismember(a,b);
tf = find(tf);
[~,idx] = unique(loc(tf), 'first');
c = tf(idx);

结果如下:
>> c
c =
     3     6     5

4
你可以尝试这样做:
[c,ind_a] = intersect(a,b)

4
a = [1, 2, 5, 7, 6, 9, 8, 3, 4, 7, 0, 6];
b = [5, 9, 6];
[r c]=find(bsxfun(@eq,a,b')');
[~,ia,~]=unique(c,'first');
>> r(ia)

ans =

     3
     6
     5

注意:我在a的末尾添加了一个额外的6,以演示仅查找每个值的第一次出现。

1
a = [1, 2, 5, 7, 6, 9, 8, 3, 4, 7, 0];
b = [5, 9, 6];
c = dsearchn(a',b');

Matlab需要a和b作为列向量,因此需要转置。

1
你尝试过使用 ismember 吗?
c_logical_mask = ismember(a, b);

或者

c_indexes = find(ismember(a, b));

2
有几件事情需要注意:这个方法并不仅仅是在a中找到b的每个值的第一次出现,而且它也不能按正确的顺序保留索引。 - tmpearce
@tmpearce:我发布了一个修复。 - Amro

1
@tmpearce的回答类似,但可能更快:
[valid, result] = max(bsxfun(@eq, a(:), b(:).')); %'// max finds first occurrence
result = result(valid); %// this is necessary in case some value of b is not in a

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接