我试图在向量中找到与另一个向量对应的元素索引,最好不使用循环。例如,我的输入可能是:
DJiSet = [5 7 8]; % elements of which I need the indices
JiSet = [3 4 5 6 7 8 9 11 12 20]; % vector to search
这里的输出是:
[3 5 6]
到目前为止,我提出的最快的是:
Output = find(ismember(JiSet,DJiSet));
但是我觉得这可以更快地完成,特别是因为我认为find
命令相当慢。
注意事项:
DJiSet
JiSet
中的值都存在
JiSet
始终按升序排序,无需重复输入DJiSet
JiSet
答案 0 :(得分:10)
方法#1
您可以通过在find
内反转DJiSet
和JiSet
的位置来避免ismember
,然后使用第二个输出来为我们提供匹配的索引 -
[~,out] = ismember(DJiSet,JiSet)
方法#2
可以尝试满足问题中设定的特定条件的Loopy方法,但不确定这是否会更有效 -
intv_idx = zeros(1,numel(DJiSet));
intv_idx(1) = find(JiSet==DJiSet(1),1);
start = intv_idx(1)+1;
for k = 2:numel(DJiSet)
idx = find(JiSet(start:end)==DJiSet(k),1);
start = idx+start;
intv_idx(k) = idx;
end
out = cumsum(intv_idx);
答案 1 :(得分:5)
Divakar's answer是要走的路。但是如果你想手动更多的话:
[~, Output] = max(bsxfun(@eq, DJiSet(:).', JiSet(:)), [], 1);
如果有多个,则会找到第一个。
如果DJiSet
中JiSet
中的值无法保证出现在[val, Output] = max(bsxfun(@eq, DJiSet(:).', JiSet(:))); %'
Output(~val) = 0; %// 0 indicates "not found"
中,您可以使用一个小修改:
{{1}}
答案 2 :(得分:5)
对于小型数据集,似乎我的原始方法比Divakar提出的ismember
解决方案和qmeeeeeee提出的intersect
解决方案更快,但所有三个都被打败了通过路易斯·门多的解决方案,使用优秀的bsxfun
。请参阅下面的代码,每种方法的次数:
function somescript()
IsmemberTime = timeit(@membersol)
IntersectTime = timeit(@intersectsol)
FindTime = timeit(@naivesol)
BsxTime = timeit(@bsxfunsol)
function membersol()
rng(1)
set = randi(30,[1000 15]); % generate 1000 vectors of length 15, containing random integers
for i=1:1000
[~,out] = ismember(set(i,1:5),set(i,6:end)); % first 5 random integers are the values to be found in the remainder of the vector
end
end
function intersectsol()
rng(1)
set = randi(30,[1000 15]);
for i=1:1000
[~,~,Output] = intersect(set(i,1:5),set(i,6:end));
end
end
function naivesol()
rng(1)
set = randi(30,[1000 15]);
for i=1:1000
Output = find(ismember(set(i,6:end),set(i,1:5)));
end
end
function bsxfunsol()
rng(1)
set = randi(30,[1000 15]);
for i=1:1000
[~, Output] = max(bsxfun(@eq, set(i,1:5).', set(i,6:end)), [], 1);
end
end
end
在我的机器上运行(运行R2014b)会返回以下时间:
IsmemberTime =
0.1101
IntersectTime =
0.2008
FindTime =
0.0698
BsxTime =
0.0218
这表明,对于小数据集,至少在向量的反转顺序上使用find
和ismember
实际上比单独使用ismember
更快。由于生成用于测试的数据集set
的所有方法也有一些固定的开销,因此差异似乎相当大。可以在下面的评论中找到更全面的测试。
答案 3 :(得分:4)
也许你可以试试相交?假设速度要快得多:
[Intersect,indDJiSet,indJiSet] = intersect(DJiSet,JiSet)
排序无关紧要,只要元素存在于两个列表中,ind元素就会给出索引。