Genetics
Genetics

Reputation: 75

MATLAB quick find of a vector in matrix

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?

Upvotes: 2

Views: 198

Answers (5)

gnovice
gnovice

Reputation: 125874

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]));

Upvotes: 0

CKT
CKT

Reputation: 781

R2016b and beyond:

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

Prior:

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

Upvotes: 1

rahnema1
rahnema1

Reputation: 15867

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)

Upvotes: 0

Javidan
Javidan

Reputation: 114

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.

Upvotes: 0

souty
souty

Reputation: 607

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.

Upvotes: 1

Related Questions