I have a structure array like:
points = struct('x',[],'y',[],'z',[])
with many points in it
points(1).x = 3
points(1).y = 4.5
points(1).z = 1
...
points(n).x = 2
points(n).y = 23
points(n).z = 4
now given three coordinates (x,y,z), I would like to now if there is such a point in points
. I've therefore defined the following function:
function true_or_false = is_in(points, point)
for i = 1:numel(points)
if abs(points(i).x - point.x) < 1e-7 && ...
abs(points(i).y - point.y) < 1e-7 && ...
abs(points(i).z - point.z) < 1e-7
true_or_false = true;
return
end
end
true_or_false = false;
end
The problem is that this is quite inefficient. Is there a better way to do this? Perhaps using something else instead of structures?
You can vectorize this operation by exploiting Matlab's ability to "catch" comma-separated lists inside square or curly brackets, as in [s.fieldname]
or {s.fieldname}
. A "comma-separated list" is generated implicitly when you de-reference a field of a multi-element struct
, and in your case since each exemplar is a scalar, there's no problem concatenating these inside square brackets, to give you a 1-by-n numeric vector for each coordinate, [points.x]
, [points.y]
and [points.z]
. Then you might do something like:
function [true_or_false, matches] = is_in(points, point)
matches = abs([points.x] - point.x) < 1e-7 & abs([points.y] - point.y) < 1e-7 & abs([points.z] - point.z) < 1e-7;
true_or_false = any(matches);
The more-general case (where your field values might not be scalars, or might not be numeric) probably cannot be made more efficient than your looped approach.