This is a general question, not related to a particular operation. I would like to be able to write the results of an arbitrary function into elements of a cell array without regard for the data type the function returns. Consider this pseudocode:
zout = cell(n,m);
myfunc = str2func('inputname'); %assume myfunc puts out m values to match zout dimensions
zout(1,:) = myfunc(x,y);
That will work for “inputname” == “strcat” , for example, given that x and y are strings or cells of strings with appropriate dimension. But if “inputname” == “strcmp” then the output is a logical array, and Matlab throws an error. I’d need to do
zout(1,:) = num2cell(strcmp(x,y));
So my question is: is there a way to fill the cell array zout without having to test for the type of variable generated by myfunc(x,y ? Should I be using a struct in the first place (and if so, what’s the best way to populate it)?
(I’m usually an R user, where I could just use a list variable without any pain)
Edit: To simplify the overall scope, add the following “requirement” :
Let’s assume for now that, for a function which returns multiple outputs, only the first one need be captured in zout . But when this output is a vector of N values or a vector of cells (i.e. Nx1 cell array), these N values get mapped to zout(1,1:N) .
The answer provided by @NotBoStyf is almost there, but not quite. Cell arrays are the right way to go. However, the answer very much depends on the number of outputs from the function.
Functions with only one output
The function
strcmphas only one output, which is an array. The reason thatgives you an error message, when zout is dimensioned N x 2, is that the left-hand side (
zout{1,:}) expects two outputs from the right-hand side. You can fix this with:However, there’s really no reason to do this. You can simply define
zoutas an N x 1 cell array and capture the results:There’s one more case to consider…
Functions with multiple outputs
If your function produces multiple outputs (as opposed to a single output that is an array), then this will only capture the first output. Functions that produce multiple outputs are defined like this:
Here, you need to explicitly capture both output arguments. Otherwise, you just get
a. For example:This can also be done programmatically, with some limits. Let’s say we’re given function
functhat takes one input and returns a constant (but unknown) number of outputs. Wehave cell array
inpthat contains the inputs we want to process, and we want to collect the results in cell aroundoutp:This approach has a few caveats:
It captures all of the outputs. This is not always what you want.
Capturing all of the outputs can often change the behavior of the function. For example, the
findfunction returns linear indices if only one output is used, row/column indices if two outputs are used, and row/column/value if three outputs are used.It won’t work for functions that have a variable number of outputs. These functions are defined as
function [a,b,...,varargout] = func( ... ).nargoutwill return a negative number if the function hasvarargoutdeclared in its output list, because there’s no way for Matlab to know how many outputs will be produced.Unpacking array and cell outputs into a cell
To provide a uniform output syntax for all functions that return either a cell or an array, use an adapter function. Here is an example that handles numeric arrays and cells:
To unpack the output into a 2-D cell array, the size of each output must be constant. Assuming
Moutputs:The output can then be addressed as
outp{i,j}. An alternate approach allows the size of the output to vary:The output can then be addressed as
outp{i}{j}, and the size of the output can vary.A few things to keep in mind:
Matlab cells are basically inefficient pointers. The JIT compiler does not always optimize them as well as numeric arrays.
Splitting numeric arrays into cells can cost quite a bit of memory. Each split value is actually a numeric array, which has size and type information associated with it. In numeric array form, this occurs once for each array. When the array is split, this incurs once for each element.