MATLAB quick find of a vector in matrix

一个人想着一个人 提交于 2020-01-15 07:53:27

问题


I have a piece of code that works in the following way. There is a matrix of size n x 2. Each element is an integer between 1 and some maximum, say m.

I want to search for rows in this matrix, that is, given [v1, v2], output the index of this.

Right now, I am using:

k = find(ismember(edges, [v1, v2], 'rows'));

However, this is the bottleneck in my code because this is in linear time.

I would like to implement some hashmap type structure for fast lookup. What would be an easy way to do this?


回答1:


Since you know the number of columns how about this (assuming edges is the matrix to be searched):

idx = find(edges(:,1)==v1 & edges(:,2)==v2);

Note, that depending on how exactly you use the index you might be better off using the logical index that is created on the way:

idx = edges(:,1)==v1 & edges(:,2)==v2;

Hope this helps.




回答2:


R2016b and beyond:

find(all(edges == [v1 v2], 2))

Prior:

find(all(bsxfun(@eq, edges, [v1 v2]), 2))



回答3:


Try the following code:

M = [5 2; 10 1; 3 2; 4 4; 5 0]
N = [4 4]
ind=find(all(repmat(N,size(M,1),1)==M,2));

ind is the row where the matrix include the specific numbers in N.




回答4:


Using accumarray can make an adjacency matrix to speed up your search:

A = accumarray(edges,1,[m m],@any,false)

and you can use indexing to search it

if(A(v1,v2))...

If m is very large you can create a sparse matrix:

A = accumarray(edges,1,[m m],@any,false,true)

Or if you need index of it the adjacency matrix can be cereated this way:

A = accumarray(edges,1:size(edgaes,1),[m m],@any,0,true);

so

index = A(v1,v2)



回答5:


One option that gives me about a 30-40 times speedup over your code is doing the comparison for the entire first column, capturing a set of indices, then only checking the values of the second column at those indices:

ind = find(edges(:, 1) == v1);
k = ind(edges(ind, 2) == v2);

If you still need it done faster than that, you can use the containers.Map class to precompute a mapping of every possible [v1 v2] to the list of row indices where it occurs. One caveat is that the key type for the map can't be a vector of numbers, but since you are dealing with integers (ideally with m not being prohibitively large) you can convert [v1 v2] to a 2-character ASCII key. Here's how you can build the map:

mapObj = containers.Map('KeyType', 'char', 'ValueType', 'any');
[R, C] = meshgrid(1:m);
keys = [R(:) C(:)];
for keyIndex = 1:(m*m)
  v = keys(keyIndex, :);
  ind = find(edges(:, 1) == v(1));
  mapObj(char(v)) = ind(edges(ind, 2) == v(2));
end

And you can access a value from the map very quickly like so:

k = mapObj(char([v1 v2]));


来源:https://stackoverflow.com/questions/43445463/matlab-quick-find-of-a-vector-in-matrix

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!