查找符合多个条件的元素

Wou*_*ers 8 matlab

我试图在向量中找到与另一个向量对应的元素索引,最好不使用循环.例如,我的输入可能是:

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
Run Code Online (Sandbox Code Playgroud)

这里的输出是:

[3 5 6]
Run Code Online (Sandbox Code Playgroud)

到目前为止,我提出的最快的是:

Output = find(ismember(JiSet,DJiSet));
Run Code Online (Sandbox Code Playgroud)

但是我觉得这可以更快地完成,特别是因为我认为find命令相当慢.

注意事项:

  • DJiSet保证所有值都存在于中JiSet
  • JiSet 始终按升序排序,无需重复输入
  • DJiSet不保证连续找到矢量JiSet

Div*_*kar 10

方法#1

您可以find通过反转内部DJiSetJiSet内部的位置来避免ismember,然后使用第二个输出来为我们提供匹配的索引 -

[~,out] = ismember(DJiSet,JiSet)
Run Code Online (Sandbox Code Playgroud)

方法#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);
Run Code Online (Sandbox Code Playgroud)

  • 打败我几秒哈哈+1 (2认同)

Lui*_*ndo 5

迪瓦卡的答案是要走的路.但是如果你想手动更多:

[~, Output] = max(bsxfun(@eq, DJiSet(:).', JiSet(:)), [], 1);
Run Code Online (Sandbox Code Playgroud)

如果有多个,则查找第一次出现.

如果值DJiSet不能保证存在于JiSet,你可以使用一个小的修改:

[val, Output] = max(bsxfun(@eq, DJiSet(:).', JiSet(:))); %'
Output(~val) = 0; %// 0 indicates "not found"
Run Code Online (Sandbox Code Playgroud)


Wou*_*ers 5

对于小型数据集,似乎我的原始方法比ismemberDivakar提出的解决方案和intersectqmeeeeeee提出的解决方案都快,但所有三个都被Luis Mendo的解决方案打败了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
Run Code Online (Sandbox Code Playgroud)

在我的机器上(运行R2014b)返回以下时间:

IsmemberTime =

    0.1101


IntersectTime =

    0.2008


FindTime =

    0.0698


BsxTime =

    0.0218
Run Code Online (Sandbox Code Playgroud)

这表明,对于小数据集至少,使用findismember基于矢量的反转顺序实际上比ismember单独使用更快.由于生成set用于测试的数据集的所有方法也有一些固定的开销,因此差异似乎相当大.可以在下面的评论中找到更全面的测试.