How can I check whether an element is in a nested cell array? - arrays

How can I check whether an element is in a nested cell array?
ex:
A = {{4 5 6};{6 7 8}};
b = 5;
The function
ismember(b,A{1})
does not work.
Is there any solution better than for-loop?

Because each element is a cell, you don't have a choice but to use cellfun combined with ismember, which is the same as using a loop in any case. Your cells are specifically two-deep (per Andrew Janke). Each cell element in your cell array is another cell array of individual elements, so there is no vectorized solution that can help you out of this.
Assuming that each cell is just a 1-D cell array of individual elements, you would thus do:
A = {{4 5 6};{6 7 8}};
b = 5;
out = cellfun(#(x) ismember(b, cell2mat(x)), A);
Which gives us:
out =
1
0
This checks to see if the value b is in each of the nested cell arrays. If it is your intention to simply check for its existence over the entire nested cell array, use any on the output, and so:
out = any(cellfun(#(x) ismember(b, cell2mat(x)), A));
Because each cell element is a cell array of individual elements, I converted these to a numerical vector by cell2mat before invoking ismember.

Related

Sub2ind with three dimension - access all of dimension

Say A is a 3x4x5 array. I am given a vector a, say of dimension 2 and b of dimension 2. If I do A(a,b,:) it will give 5 matrices of dimensions 2x2. I instead want the piecewise vectors (without writing a for loop).
So, I want the two vectors of A which are given by (a's first element and b's first element) and (a's second element and b's second element)
How do I do this without a for loop? If A were two dimensions I could do this using sub2ind. I don't know how to access the entire vectors.
You can use sub2ind to find the linear index to the first element of each output vector: ind = sub2ind(size(A),a,b). To get the whole vectors, you can't do A(ind,:), because the : has to be the 3rd dimension. However, what you can do is reshape A to be 2D, collapsing the first two dimensions into one. We have a linear index to the vectors we want, that will correctly index the first dimension of this reshaped A:
% input:
A = rand(3,4,5);
a = [2,3];
b = [1,2];
% expected:
B = [squeeze(A(a(1),b(1),:)).';squeeze(A(a(2),b(2),:)).']
% solution:
ind = sub2ind(size(A),a,b);
C = reshape(A,[],size(A,3));
C = C(ind,:)
assert(isequal(B,C))
You can change a and b to be 3d arrays just like A and then the sub2ind should be able to index the whole matrix. Like this:
Edit: Someone pointed out a bug. I have changed it so that a correction gets added. The problem was that ind1, which should have had the index number for each desired element of A was only indexing the first "plane" of A. The fix is that for each additional "plane" in the z direction, the total number of elements in A in the previous "planes" must be added to the index.
A=rand(3,4,5);
a=[2,3];
b=[1,2];
a=repmat(a,1,1,size(A,3));
b=repmat(b,1,1,size(A,3));
ind1=sub2ind(size(A),a,b);
correction=(size(A,1)*size(A,2))*(0:size(A,3)-1);
correction=permute(correction,[3 1 2]);
ind1=ind1+repmat(correction,1,2,1);
out=A(ind1)

Targeting specific elements of cell arrays (Matlab)

I currently have a cell array consisting of 7x1 vectors. I need to extract the first element (1,1) of each vector from each cell and store these values in a new array. This is what I currently have:
for j = 1:numel(xvalues)
cellj = xvalues{j};
a = cellj(1:1);
avalues(1:j) = a;
end
However, I am just generating a cell array with the first element of the last cell, repeating.
How can I fix this?
You can also use cellfun to apply a function to each element in a cell array. So to extract the first element of each vector the following should work.
avalues = cellfun(#(x) x(1),xvalues);
Cellfun loops through each element in the cell array and passes it in to the anonymous function via #(x). We then process x by taking the first element x(1).
In cases such as yours, where the cell contents are matrices of the same size, and assuming your inputs are small enough (meaning that neither memory nor runtime are imminent issues) you can convert the cell array into a numeric matrix and select a vector along the relevant dimension:
function out = q48740494
%% Generate some data:
c = squeeze(num2cell(randi(20,7,1,20),[1,2]));
% c = 20×1 cell array of {7x1 double}
%% Convert this into a numeric array and output:
out = cell2mat(c.'); out = out(1,:);
% BONUS: another version of the line above.
% out = subsref(cell2mat(c.'), substruct('()', {1,1:numel(c)}) ) ;

Applying Movmedian Within Cell Array

I have a cell array (2 x 6) called "output", each cell in row #1 {1 -> 6, 2} contains a 1024 x 1024 x 100 matrix. I want to apply movmedian to each cell in row #1. I would like to apply this function in dimension = 3 with window size = 5.
output = cellfun(#movmedian(5,3), output,'uniform', 0);
This is the code that I have come up with so far, however, it produces an "unbalenced or unexpected parenthesis or bracket" error. I am unsure what is causing this error. I am also somewhat unsure how to instruct matlab to perform this operation only on row 1 of the cell array, please help!
Thank you for your time!!
The function handle passed as the first argument to cellfun will be sequentially passed the contents of each cell (i.e. each 3-D matrix). Since you need to also pass the additional parameters needed by movmedian, you should create an anonymous function like so:
#(m) movmedian(m, 5, 3)
Where the input argument m is the 3-D matrix. If you want to apply this to the first row of output, you just have to index the cell array like so:
output(1, :)
This will return a cell array containing the first row of output, with : indicating "all columns". You can use the same index in the assignment if you'd like to store the modified matrices back in the same cells of output.
Putting it all together, here's the solution:
output(1, :) = cellfun(#(m) movmedian(m, 5, 3), output(1, :),...
'UniformOutput', false);
...and a little trick to avoid having to specify 'UniformOutput', false is to encapsulate the results of the anonymous function in a cell array:
output(1, :) = cellfun(#(m) {movmedian(m, 5, 3)}, output(1, :));

which structure I should use for this matlab arrays

I'm starting to develop a project which uses multi-dimensional arrays very often.
my arrays are mostly 2 , 3 dimensional or so.
As a 2D array sample consider 'A', I may have 2 or more 1D arrays in a cell.
sth like
A=[1, [78,9] [10,65], 9;
2 , 3 , 6;
7 , [9,1] , [91,41,96][10,-1]]
As you saw in 'A(1,2)' there are two 1D arrays.
I don't know which structure I should use to achieve such thing.
moreover I want to be able to have access to all those 1D arrays.
please share your knowledge with me.
try using cell or struct i would recommend cell.
E.g. preinitialize A1:
A1=cell(3,3)
(that would be a 3x3 cell array/matrix). Then you can adress elements with curly brackets ({}). E.g.:
A1{1,1}= 1;
A1(1,1)={1};
both work. You can also define many cells in one line. E.g:
A1(2,:) = {2,3,6};
For the cases with multiarray entries use another cell structure:
B= {[78,9], [10,65]};
A1(1,2) = {B};
and so on. Pay attention to use curly brackets around B (or the coordinate in A1)! Otherwise he would try to merge the cells from B in A1 but that won't do any good because B is a 1x2 cell and you want to give it as argument to one cell in A1.
If you want to return the value inside a cell you have to use curly brackets again:
A1{1,1}
would return 1.
It depends on what you want to do with such a structure. You could use cell arrays for each 1d array entry, and create a matrix of such cell arrays:
a = {1, 2};
b = {-1, 4, 6};
M = [a b];
Alternatively, you can define a sparse 3d array.

How to use cell arrays in Matlab?

I am a beginner at using Matlab and came across cell arrays but I am not sure how to use indexing for it.
I have created a cell array of 5 rows and 3 cols by doing the following:
A = cell(5,3);
Now is it possible to go through the cell array by row first and then col like how a nested for loop for a normal array?
for i=1:5
for j=1:3
A{i,j} = {"random"} //random numbers/ string etc
end
end
With cell arrays you have two methods of indexing namely parenthesis (i.e. (...)) and braces (i.e. {...}).
Lets create a cell array to use for examples:
A = {3, 9, 'a';
'B', [2,4], 0};
Indexing using paranthesis returns a portion of the cell array AS A CELL ARRAY. For example
A(:,3)
returns a 2-by-1 cell array
ans =
'a'
0
Indexing using braces return the CONTENTS of that cell, for example
A{1,3}
returns a single character
ans =
a
You can use parenthesis to return a single cell as well but it will still be a cell. You can also use braces to return multiple cells but these return as comma separated lists, which is a bit more advanced.
When assigning to a cell, very similar concepts apply. If you're assigning using parenthesis, then you must assign a cell matrix of the appropriate size:
A(:,1) = {1,1}
if you assign a single value using parenthesis, then you must put it in a cell (i.e. A(1) = 2 will give you an error, so you must do A(1) = {2}). So it's better to use braces as then you are directly affecting the contents of the cell. So it is correct to go
A{1} = 2
this is equivalent to A(1) = {2}. Note that A{1} = {2}, which is what you've done, will not give a error but what is does is nests a cell within your cell which is unlikely what you were after.
Lastly, if you have an matrix inside one of your cells, then Matlab allows you to index directly into that matrix like so:
A{2,2}(1)
ans =
3
for example:
for i=1:5
for j=1:3
A{i,j} = rand(3)
end
end
should work perfectly fine
just skip the { } on the right side of the =

Resources