Append values to several cells in cell array - matlab

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.

Related

Basic Matlab for loop

A=2;
for x=0:2:4
A=[A, A*x];
end
A
I'd appreciate any help! The for loop condition as well as the 3rd line and how they work together I can't quite piece together
So, here comes the walktrough.
A = 2;
A is an array of length 1, with 2 as the only element.
for x = 0:2:4
Have a look at the Examples section of the for help. You create an "iteration variable" x, which iterates through an array with the values [0, 2, 4]. See also the Examples section of the : operator help.
A = [A, A*x];
Concatenate array A with the value of A*x (multiplying an array with a scalar results in an array of the same length, in which each element is multiplied by the given scalar), and re-assign the result to A. See also the help on Concatenating Matrices.
Initially, A = [2].
For x = 0: A = [[2], [2] * 0], i.e. A = [2, 0].
For x = 2: A = [[2, 0], [2, 0] * 2], i.e. A = [2, 0, 4, 0].
For x = 4: A = [[2, 0, 4, 0], [2, 0, 4, 0] * 4], i.e. A = [2, 0, 4, 0, 8, 0, 16, 0].
end
End of for loop.
A
Output content of A by implicitly calling the display function by omitting the semicolon at the end of the line, see here for explanation.

MATLAB replacing certain values of matrix with another matrix

I have an arbitrary matrix, a = [1, 0, 0, 1].
I want to replace every 0 value with the values of another matrix b = [1, 2, 3], and every 1 value with the value of yet another matrix c = [3, 4, 5].
I would therefore end up with the matrix [3, 4, 5, 1, 2, 3, 1, 2, 3, 3, 4, 5].
I've tried finding the indices of the 0 and 1 values and replacing the values at those indices with b and c, but this isn't allowed since they aren't the same size. Is there any simple way of achieving this?
Given
a = [1, 0, 0, 1];
b = [1, 2, 3];
c = [3, 4, 5];
Let's first take the arrays we want in the final matrix and put them in a cell array:
parts = {b, c}
parts =
{
[1,1] =
1 2 3
[1,2] =
3 4 5
}
The goal is to use the values of a as indices into parts, but to do that we need all of the values to be positive from 1 to some n (if there are missing values it'll take a bit more work). In this case we can just increment a:
a_inds = a + 1
a_inds =
2 1 1 2
Now we can get a new cell array by doing parts(a_inds), or a matrix by adding cell2mat:
result = cell2mat(parts(a_inds))
result =
3 4 5 1 2 3 1 2 3 3 4 5
This can also be done with a key:value map.
a = [1, 0, 0, 1];
b = [1, 2, 3];
c = [3, 4, 5];
keyset = [1,0];
valueset = {b,c};
mapobj = containers.Map(keyset,valueset);
new_vec = [];
for i =1:length(a)
new_vec(length(new_vec)+1:length(new_vec)+length(mapobj(a(i))))= mapobj(a(i));
end
1 is mapped to b and 0 mapped to c. The for loop iterates over a building an ever longer vector containing the mapped values.
This code will allow for non-sequential keys such that 37 could be added and mapped to another vector, whereas in the previous answer you would have to map 2 to the next vector in order for the code not to break.

How to implement a function similar to cellfun?

My problem is about passing parameters to the other function; I don't know how to divide varargin and pass values as parameters.
function A = mycellfun(func, varargin)
A = cell(size(varargin{1}));
for ii = 1:numel(A)
A{i} = func(varargin{ ??? })
end
end
...
S = mycellfun(#plus, {1 [2 3]}, {4 [5 6]})
You need to use cellfun to group corresponding entries in each of the elements in varargin
inputs = cellfun(#(varargin)varargin, varargin{:}, 'UniformOutput', false);
The anonymous function #(varargin)varargin accepts a variable number of inputs (varargin) as a cell array and then simply returns this cell array. It's actually no different than the function:
function v = func(varargin)
v = varargin;
end
So for example:
varargin = {{1, 2, 3}, {4, 5, 6}};
inputs = cellfun(#(varargin)varargin, varargin{:}, 'UniformOutput', false);
% {{1, 4}, {2, 5}, {3, 6}}
And then you can loop through inputs and each cell element will contain all inputs for a given iteration. You can then use {:} indexing to create a comma separated list and pass this as inputs to func.
A = cell(size(inputs));
for k = 1:numel(inputs)
A{k} = func(inputs{k}{:});
end

Apply a cell array of functions to a value

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];

Create a matrix according to a binary matrix

Here I got
A = [1, 2, 3]
B = [1, 0, 0, 1, 0, 1]
I want to create a matrix
C = [1, 0, 0, 2, 0, 3]
You can see B is like a mask, The number of ones in B is equal to the number of elements in A. What I want is arrange elements in A to the place where B is 1.
Any method without loop?
Untested, but should be close:
C = zeros(size(B));
C(logical(B)) = A;
This relies on logical indexing.