How to get multiple outputs of a function in a vector? - matlab

Say I have a function whose outputs are two reals a and b
[a,b]=function(c)
I'd like to get all the outputs in a vector v.
v=function(c) doesn't do what I want, v is 'a' only.
Of course here I could do v=[a,b].
But the function in question is ind2sub for a N-D array so it gives n outputs that I'd like to have in a vector directly.
Is there a way to do it?
Thanks very much!

You can use a cell array and a comma-separated list like so:
X = cell(N, 1);
[X{:}] = function(C);
The syntax X{:} is in fact expanded to [X{1}, X{2}, ...], which provides a valid sink for your function. As a result, each output variable will be stored in a different cell in X.
If each output variable is a scalar, you can flatten out the cell array into a vector by using yet another comma-separated list expansion:
v = [X{:}];

Related

MATLAB: return both arguments from ISMEMBER when used inside SPLITAPPLY

How can I access both arguments of ismember when it is used inside splitapply?
slitapply only returns scalar values for each group, so in order to compute nonscalar values for each group (as returned by the first argument of ismemebr), one has to enclose the anonymous function (in this case ismember) inside curly brackets {} to return a cell array.
But now, when I provide two output arguments to splitapply, I get an error:
Output argument "varargout{2}" (and maybe others) not assigned during call to
"#(x,y) {ismember(x,y)}"
ADD 1
I can create another function, say, ismember2cell which would apply ismember and turn outputs into cell arrays:
function [a, b] = ismember2cell(x,y)
[a,b] = ismember(x,y);
a = {a};
b = {b};
end
but maybe there is a solution which doesn't require this workaround.
One potentially faster option is to just do what splitapply is already doing under the hood by splitting your data into cell arrays (using functions like mat2cell or accumarray) and then using cellfun to apply your function across them. Using cellfun will allow you to easily capture multiple outputs (such as from ismember). For example:
% Sample data:
A = [1 2 3 4 5];
B = [1 2 1 5 5];
G = [1 1 1 2 2]; % Group index
% Group data into cell arrays:
cellA = accumarray(G(:), A(:), [], #(x) {x(:).'}); % See note below about (:).' syntax
cellB = accumarray(G(:), B(:), [], #(x) {x(:).'});
% Apply function:
[Lia, Locb] = cellfun(#ismember, cellA, cellB, 'UniformOutput', false);
NOTE: My sample data are row vectors, but I had to use the colon operator to reshape them into column vectors when passing them to accumarray (it wants columns). Once distributed into a cell array, each piece of the vector would still be a column vector, and I simply wanted to keep them as row vectors to match the original sample data. The syntax (:).' is a colon reshaping followed by a nonconjugate transpose, ensuring a row vector as a result no matter the shape of x. In this case I probably could have just used .', but I've gotten into the habit of never assuming what the shape of a variable is.
I cannot find a global solution, but the accepted answer of this post helps me to define a helper function for your problem:
function varargout = out2cell(varargin)
[x{1:nargout}]=feval(varargin{:});
varargout = num2cell(x);
I think that you may succeed in calling
splitapply(#(x,y) out2cell(#ismember, x, y), A, B);

How to create an empty array in a matrix

How to create an empty array in matlab that accepts elements from a matrix when you do not know the no.of elements it is going to contain ?
Use the [] operator. Example:
x = [];
If you wanna be specific in the type of the empty matrix, use the empty property. Examples:
emptyDoubleMatrix = double.empty; % Same as emptyDoubleMatrix = [];
emptySingleMatrix = single.empty;
emptyUnsignedInt8Matrix = uint8.empty;
This works for empty matrices of classes as well. Example:
emptyFunctionHandleMatrix = function_handle.empty;
You can use the empty matrix/vector notation, [], and Matlab will set up a placeholder for it.
x = []
Now if you want to append a scalar, say num, to it, you cannot index it because it is empty.
However, you can either:
Use array concatenation to concatenate itself with another scalar:
x = [x num]
Use the end+1 notation, to address the first available location:
x(end+1) = num
Both of the above two notations also work when you want to append a row or a column vector to an existing row vector or column vectors. But when you are concatenating vectors/matrices, remember to be consistent with the dimensions.

How to split an array as argument values in matlab?

In my matlab script, I have a function handler
F=#(x1,x2)6+2*x1^1+3*x2^2;
This gives me an anonymous function as F that takes 2 arguments and returns the value. I also have an array of values
x = [1 2];
With the above, how can I do
F(x)
In other words, something like F(1, 2) but I want to use x, I don't want to hard code values, and it also needs to work for any dimension size, I don't want to hard code it for 2-dimension like in the above example. Basically what I'm looking for is a way to turn an array into arguments.
Can this be done in matlab?
Thanks
To turn an array into its arguments: first turn the array into a cell array (with num2cell), and then turn the cell array into a comma-separated list (with {:}):
xcell = num2cell(x);
F(xcell{:})
Does this work?
F=#(x)6+2*x(1)^1+3*x(2)^2;
xx = [1 2];
F(xx)
ans =
20

Create an 2-D empty array in Matlab

I would like to use union in Matlab to merge a series of 1-by-2 arrays for example [1,2] to an empty 2-D array U, i.e., U = union(U,[1,2],'rows'); But I'm confused how to initialize U, because U=[] didn't work, no luck with U=[[],[]] either. I tried U = [U,[1,2]], it works only when the 1-by-2 arrays in the series are all unique, or I would have duplicate entries in U.
So you want to get all the unique 1x2 arrays in a 2-D matrix? First, create a big 2-D array of all 1x2 arrays (including duplicates), then call unique.
C = unique(A,'rows')
As for using union, there is no way to have a empty 1x2 array. What you can do instead is initialize U to be the same as your first 1x2 array. Then loop over all the other 1x2 arrays and use union to build your output.
U = union(U, [1,2], 'rows')

Is there a splat operator (or equivalent) in Matlab?

If I have an array (of unknown length until runtime), is there a way to call a function with each element of the array as a separate parameter?
Like so:
foo = #(varargin) sum(cell2mat(varargin));
bar = [3,4,5];
foo(*bar) == foo(3,4,5)
Context: I have a list of indices to an n-d array, Q. What I want is something like Q(a,b,:), but I only have [a,b]. Since I don't know n, I can't just hard-code the indexing.
There is no operator in MATLAB that will do that. However, if your indices (i.e. bar in your example) were stored in a cell array, then you could do this:
bar = {3,4,5}; %# Cell array instead of standard array
foo(bar{:}); %# Pass the contents of each cell as a separate argument
The {:} creates a comma-separated list from a cell array. That's probably the closest thing you can get to the "operator" form you have in your example, aside from overriding one of the existing operators (illustrated here and here) so that it generates a comma-separated list from a standard array, or creating your own class to store your indices and defining how the existing operators operate for it (neither option for the faint of heart!).
For your specific example of indexing an arbitrary N-D array, you could also compute a linear index from your subscripted indices using the sub2ind function (as detailed here and here), but you might end up doing more work than you would for my comma-separated list solution above. Another alternative is to compute the linear index yourself, which would sidestep converting to a cell array and use only matrix/vector operations. Here's an example:
% Precompute these somewhere:
scale = cumprod(size(Q)).'; %'
scale = [1; scale(1:end-1)];
shift = [0 ones(1, ndims(Q)-1)];
% Then compute a linear index like this:
indices = [3 4 5];
linearIndex = (indices-shift)*scale;
Q(linearIndex) % Equivalent to Q(3,4,5)