Find a vector in a structure

3 vues (au cours des 30 derniers jours)
Alessandro Masullo
Alessandro Masullo le 16 Jan 2012
Hello! I've this structure:
>> vortex(:).points
ans =
1 2 3
4 5 6
7 8 9
ans =
9 9 9
8 8 8
I want to find the [8 8 8] vector in any of the vortex array and the position in both the vortex and the points array. Something like:
find([8 8 8], vortex) --> vortex(2).points(2, :)
find([7 8 9], vortex) --> vortex(1).points(3, :)
How should I do?

Réponse acceptée

Andrei Bobrov
Andrei Bobrov le 17 Jan 2012
variant
pall = cat(1,vortex(:).points);
a = find(ismember(pall,[7 8 9],'rows'));
b = cumsum([0 arrayfun(@(x) size(x.points,1), vortex)]);
[i1 i1] = histc(a,b+100*eps);
d = a - b;
j1 = d(find(d>0,1,'last'));
out = vortex(i1).points(j1,:)

Plus de réponses (1)

David Young
David Young le 16 Jan 2012
One method:
% Test data
vortex(1).points = [1 2 3; 4 5 6; 7 8 9];
vortex(2).points = [9 9 9; 8 8 8];
searchv = [9 9 9];
% Analyse structure to find how many rows are in each points matrix.
% No need to repeat this line if searchv changes, only if vortex does.
rowsums = cumsum([0 arrayfun(@(x) size(x.points, 1), vortex)]);
% Assemble all the points arrays into one big array, and look for the first
% row that is the same as the search vector.
row = find(~any(bsxfun(@minus, vertcat(vortex(:).points), searchv), 2), 1);
% check that a matching row has been found, to avoid an obscure error later
if isempty(row)
error('Vector not found');
end
% Convert the overall row number into the structure and array indices,
% so that vortex(struct_index).points(points_index,:) is equal
% to searchv.
struct_index = find(row <= rowsums, 1) - 1
points_index = row - rowsums(struct_index)
EDIT Revised code below, inspired by andrei bobrov's answer, making use of ismember and separating out building the large matrix.
% Analyse structure to find how many rows are in each points matrix, and
% concatenate the points matrices into one big matrix.
% No need to repeat these two lines if searchv changes, only if vortex does.
rowsums = cumsum([0 arrayfun(@(x) size(x.points, 1), vortex)]);
pall = vertcat(vortex(:).points);
% Look for the last row that is the same as the search vector.
[~, row] = ismember(searchv, pall, 'rows');
% check that a matching row has been found, to avoid an obscure error later
if ~row
error('Vector not found');
end
% Convert the overall row number into the structure and array indices,
% so that vortex(struct_index).points(points_index,:) is equal
% to searchv.
struct_index = find(row <= rowsums, 1) - 1
points_index = row - rowsums(struct_index)
  2 commentaires
Alessandro Masullo
Alessandro Masullo le 17 Jan 2012
It works, but it's a bit slow...
I have to find a vector 180000*500 times, it would take a very long time...
Is there a more performant solution?
Thanks.
David Young
David Young le 17 Jan 2012
See if Andrei Bobrov's variant is faster. In particular I think his use of ismember is better than my method of subtracting and finding a line of zeros - it's certainly more elegant.
In addition, Andrei builds the big concatenated matrix ('pall') separately from searching it, and this is very sensible, because you should not rebuild it before searching for another vector.
It might be worth having a look at the structure of your whole program, to see if there is some way of avoiding building the structures in the first place, or of indexing them when they are being built.

Connectez-vous pour commenter.

Catégories

En savoir plus sur Numeric Types dans Help Center et File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by