Find a vector in a structure
2 views (last 30 days)
Show older comments
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?
0 Comments
Accepted Answer
Andrei Bobrov
on 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,:)
0 Comments
More Answers (1)
David Young
on 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 Comments
David Young
on 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.
See Also
Categories
Find more on Numeric Types in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!