Can I overload find function in Matlab?
As you know: ind = find(X) locates allnonzero elements of array X, and returns the linear indices ofthose elements in vector ind.
But when X is array of object, how can I use find function to findout elements based on these properties ?
As Lucius Domitius Ahenobarbus noted in the link he gave, there are strict rules of when you can overload functions in matlab.
Take the following class:
classdef myclass
methods
function find(self)
fprintf('find(myclass) has been called.\n');
end
end
end
And execute
X = [myclass myclass myclass]
find(X)
This gives the following output:
X =
1x3 myclass with no properties.
Methods
find(myclass) has been called.
What you do in your overloaded find function is up to you. Just write a function that prints out the indices of the elements that match what you call "these properties", whatever that is.
You can do a couple things here: overload find
, or pop out the conditions you want to search on and call the regular find
on those. It probably makes more sense to use regular find on a property-access expression.
To apply find
to objects or other structures, you can use property access syntax to create logical expressions that identify the objects that meet the conditions you're looking for, and pass those to find
. Suppose your class has a qty
property, and that's what you're searching on.
ind = find( [X.qty] ~= 0 );
You can combine these logical expressions to do more complicated searches.
ind = find( [X.ghz] > 3 && [X.cacheMB] > 2 && [X.price] < 600 )
You should probably only overload the well-known Matlab functions like find
if your object methods are going to have similar semantics. The find
function takes an array of logicals and returns numeric indexes. So it probably only makes sense for your class if the elements of that class could themselves be considered zero or nonzero values in a sense.
To overload a function to work on your class, just define a method in your class with the same name as the function. To work well with other Matlab code, it should probably accept the same typical arguments as the regular function, aside from allowing instances of your object.
Let's say your class represents points in 2-D space as (X,Y) coordinates, and you want to consider the point at the origin (0,0) to be zero, and all other points to be nonzero. You would provide a find
method that tests both those points. To make the behavior consistent with Matlab's find
, you could just implement the nonzero test in your code, and pass everything else on to the regular find
function.
class point
properties
X;
Y;
end
methods
function out = find(obj)
% Test for zero/nonzero points
x = reshape([obj.X], size(x));
y = reshape([obj.Y], size(y));
isNonzero = x + y; % Quantity is not meaningful, but covers zero/nonzero/NaN
out = find(isNonzero);
end
end
end
To be fully consistent with find
, it's a bit more complicated, because find
supports additional input and output arguments, which overloaded methods should too.
class point
properties
X;
Y;
end
methods
function varargout = find(obj, varargin)
varargout = cell(1, max(nargout, 1));
% TODO: In production code, verify that varargin does not
% contain @point objects, to avoid infinite recursion
% Test for zero/nonzero points
x = reshape([obj.X], size(obj));
y = reshape([obj.Y], size(obj));
isNonzero = x + y; % Quantity is not meaningful, but covers zero/nonzero/NaN
[varargout{:}] = find(isNonzero, varargin{:});
end
end
end
All this is kind of a pain, so you may only want to overload find
if you need polymorphic behavior from your objects: that is, if you want to pass them in to other code that is written to call find()
on its inputs. If you just need the output of find()
locally in your code, it's probably easier to do property access. Or you could just provide an isnonzero()
method for quick conversion to an input that find()
will play well with.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.