Apply a cell array of functions to a value - matlab

I define a cell array that contains values and functions:
>> A = {1, 2, 3; #(x) x+5, #(x) x+10, 5}
A =
[ 1] [ 2] [3]
#(x)x+5 #(x)x+10 [5]
Does anyone know how to apply this cell array to a value? For instance, when x = 2, the application returns another cell array:
[ 1] [ 2] [3]
[ 7] [ 12] [5]

Define your constants as functions:
A = {#(x)1, #(x)2, #(x)3; #(x) x+5, #(x) x+10, #(x)5}
now use cellfun:
k = 2;
cellfun(#(x)x(k),A)
Also note that if you want to apply multiple k values at once (e.g. k = 1:5) you will need to edit your constant functions in A from this form #(x) n to something like #(x) n*ones(size(x)) and then change the cellfun call to:
cellfun(#(x)x(k),A, 'uni',0)
To answer the question from your comments:
is it possible to refer to other cells in a function in a cell array?
For instance, can we define something like A = {#(x)1, #(x)2, the 1st cell + the 2nd cell, #(x)4}?
You define A as follows:
A = {#(x)1, #(x)2, #(x)(A{1}(x)+A{2}(x)), #(x)4}

Wouldn't it be better to define the cell-array/function thingie like this:
A = #(x) {1, 2, 3; x+5, x+10, 5};
Then you can apply it by simpliy doing
A(2)
Maybe you can even use normal matrices instead of cell array here:
A = #(x) [1, 2, 3; x+5, x+10, 5];

Related

MATLAB - subs method doesn't work on symbolic vector of indexed variables

Consider the following code:
A = sym('a', [1, 2]);
b = sym('b');
ans = A.^2 + b;
A = [1, 2];
b = 4;
subs(ans)
This yields the output
ans = [ a1^2 + 4, a2^2 + 4]
Whereas I would have wanted it to produce
ans = [ 5, 8]
What is required for the vector to be converted to numeric values aswell?
Here's a simpler solution:
syms A b; %Initializing symbolic variables
expr = A^2 + b; %Your expression (element-wise square is taken by default for sym class)
A = [1 2]; b=4; %Assigning the values
subs(expr) %Substituting symbolic variables with corresponding assigned values
Output as desired:
ans =
[ 5, 8]
Comments:
Always avoid dynamic variables. In your code, you're specifying A to be [1, 2] but your expression doesn't actually have A in it. It has a1 and a2 (and b obviously).
Don't name your variables/functions after the reserved variable names or in-built functions. ans is used for the Most Recent Answer when expressions are not assigned to anything else. (That's why I replaced ans in your code with expr)

Syntax for evaluating multiple variables for function

I'm trying to do something like
f = [x+1 y+2]
values = [1 2]
f(values) = [2 4]
(not proper syntax)
f(values) only works for taking one variable?
Try this:
f = {#(x) (x+1); #(y) (y+2)}; %//create a cell array of your function handlers
values = [1 2];
%//convert your input values to a cell array
length = numel(values);
v = mat2cell( values, 1, ones(length,1) ).' ;
%// f(v)
results = cellfun(#(x,y) x(y), f, v);

Vectorized or single line evaluation of function array in MATLAB

In a previous question, a user asked about iterating over a cell array of anonymous functions. I am wondering whether there is a way to evaluate a set of functions without the explicit use of a for loop.
As an example, the following code creates an array of (simple) functions, evaluates them for a fixed value and stores the results:
fcnList = {#(x) (x+1), #(x) (x+2)};
a = 2;
for i = 1:numel(fcnList)
y(i) = fcnList{i}(a);
end
Is there a way to do this without looping?
For your example, you could do the following using the cellfun function:
fcnList = {#(x) (x+1), #(x) (x+2)};
a = 2;
cellfun(#(func) func(a),fcnList)
ans =
3 4
Where I have created a handle called func which accepts as input a function from the fcnList variable. Each function is then evaluated for a.
If you need to pass a vector instead of a scalar, for instance b, you will need to set the 'UniformOutput' option to false:
b=[3 4]
fcnList = {#(x) (x+1), #(x) (x+2)};
cellfun(#(func) func(b),fcnList,'UniformOutput',false)
ans =
{
[1,1] =
4 5
[1,2] =
5 6
}
To avoid a for loop or cellfun (which is more or less the same as a loop), you can define a single function with vector output:
fcn = #(x) [x+1, x+2];
Then fcn(a) gives you a vector cointaining the results:
>> fcn = #(x) [x+1, x+2];
>> a = 2;
>> fcn(a)
ans =
3 4
If the results of each original function have different sizes you can define a single function with cell array output:
>> fcn = #(x) {x+1, [x+2; x+3]};
>> a = 2;
>> x = fcn(a)
x =
[3] [2x1 double]
>> celldisp(x)
x{1} =
3
x{2} =
4
5

Append values to several cells in cell array

Imagine I have a cell array
A = {0, 1 ,2, 3, ...}
and indice vector
I = [0, 1, 0, 1, 0, ...]
and values
V = [2, 3]
and I want something like
A{I} = [A{I}; V]' = {0, [1 2], 2, [3 3], ....};
That is, I want to append several values to some cells of a cell array at once. How would I do that most elegantly/efficiently? :)
You can use cellfun
A(I==1) = cellfun( #(x,y) [x y], A(I==1), num2cell(V), 'UniformOutput', 0 );
Note the usage of regular subscripting (using (), rather than {}) to index the chosen cell elements using I==1. Also note that V is passed as a cell array (using num2cell) and not as a regular array.

Octave appending in a 2D cell array

I'm trying to append an element at the end of a 2D cell array row. My code is:
b = cell(5, 0)
b(1) = {b(1, :), 2} % Trying to append at the end of the first row
This gives me the error: error: A(I) = X: X must have the same size as I
I've also tried various other forms, such as:
b = cell(5, 0)
b(1, end+1) = 2 % Ok, inserts 2 at [1,1]
b(2, end+1) = 3 % No, inserts 3 at [2,2] instead of [2, 1]
It seems that you are confused with cell array indexing.
If you want to append elements at the end of a row in a matrix (in your case, a cell array), you must still make sure that all rows are of the same size after the assignment, otherwise you'll trigger an error about mismatching dimensions.
Instead of b(1) = {b(1, :), 2}, the following should work:
b(1, end + 1) = 2
Alternatively, if you want to append an entire column array of cells to b, use horizontal concatenation, for example:
b = [b, {2; 3; 4; 5; 6}];
This should append a single cell at the end of each row of b.
The reason the element gets inserted at [2, 2] and not [1, 1] is that by the time you try to insert the second element, the value denoted by end has increased from 0 to 1.
The following should do what you need:
>> b = cell(5, 0)
b =
Empty cell array: 5-by-0
>> b(1,1) = {2}
b =
[2]
[]
[]
[]
[]
>> b(2,1) = {3}
b =
[2]
[3]
[]
[]
[]
>>