Normalize length of cell array - matlab

I have a cell array of length 3 and I want to make a for loop with another cell array with length of 6 , so how can I add extra 3 cells for the first array in order to make the 2 cell arrays equal and to use my for loop in MATLAB?
For example, with 2 inputs:
type = { '12' '62' '5' };
colour = {'re' 'green' 'yellow' 'brown' 'blue' 'black'};
for i = 1:length(colour)
if isequal(colour(i), type(:))
result(i) = type(i);
else
end
end
I need to make the type cell array with the same size with colour cell array (I think I have to add extra 3 empty cells in side the type cell array).

I have to address several issues in your code first:
If you use a cell array, you must use curly braces ({}) to extract elements from it. Instead of writing colour(i) you should be writing colour{i}.
This is not a problem, but it's a matter of good practice. If you don't need to handle the else part of the if statement, don't write it at all.
Preallocate memory so that arrays don't grow inside the loop (it slows down the program). Specifically, add the line result = cell(size(colour)); before the for loop.
Your isequal logic is flawed. Practically, it would always return false because colour{1} is one element and type{:} is many.
According to your example, types contain numbers and colours letters, although they are both strings. Does it make sense to compare the two?
Now, regarding your question, it's up to you to decide how the for loop runs. Since you don't mention what you want to achieve (you rather ask how you want to achieve something without saying what exactly), I cannot say what your for loop should look like, if necessary at all. Maybe you meant to use ismember instead of isequal? If so, the fixed code can look like this:
result = cell(size(colour));
for i = 1:length(colour)
if ismember(colour{i}, type)
result{i} = type{i};
end
end
or shorter, like this:
result = cell(size(colour));
[found, idx] = ismember(colour, type);
result(found) = type{idx(found)}
If you provide more details, maybe I can refine my answer so that it helps you more.

Related

convert cell to empty nested structure

imagine you have a cell Array "test" with two dimensions "e" and "f" of different size. Is it possible to convert this with one dimension to a struct while the other one to the substruct? It works with a Loop, but i don't like Loops. Cause the struct is empty before i can't arrange in an Array with [...].
StrA.SubA.SubSubA=struct('SubSubSubA',[],'SubSubSubB',[]);
count_e=4;
count_f=2;
for e=1:count_e
for f=1:count_f
StrA.SubA(e,1).SubSubA(f,1).SubSubSubA=test{e,f};
end
end
Thanks in advance
You can do this without loops using struct, num2cell, and a couple of transposes:
test = num2cell(rand(4, 2)); % Sample 4-by-2 cell array of random data
StrA = struct('SubA', struct('SubSubA', num2cell(struct('SubSubSubA', test, ...
'SubSubSubB', []).', 1)).');
Although I don't know if it will be any faster or more readable than the loop-based solution.
I should also note that in your loop-based solution, only substructures StrA.SubA(1).SubSubA(1) and StrA.SubA(1).SubSubA(2) will have a SubSubSubB field. All other substructures in StrA.SubA(2:4) will only contain the field SubSubSubA.

How to pre-allocate and assign a value to a variable whose name is written in a cell array?

% Data
Fields = {'History','Maths','English','French','Geography','Philosophy'}';
Students= horzcat({'5','7','3','6','10','9'}',{'6','7','7','6','10','9'}',{'5','2','3','9','1','9'}',{'1','4','9','6','6','9'}',{'8','8','3','8','10','9'}',{'5','5','5','9','8','7'}' );
Table_Score = horzcat(Fields,Students);
PS: I know there are certain ways to organize better the raw data to facilitate thing but imagine that it is an pratical case where I want to allocate cells and set values without mentionning directly the name of these variables, but calling them from the cell arrays where they are listed.
% Imagine there are much more fields of study, I will just mention a few
List_of_study_fields = {'History','Maths','English','French','Geography','Philosophy'};
nb_fields = length(List_of_study_fields);
% Imagine there are much more students, I will just mention a few
List_of_students = {'Damien','Michael','Louis', 'Daniel','Isabelle','Jessica'};
%% 1) Pre-allocate "student names" variables from the "student names" (cell array):
% Each variable is the student name in the list.
% Scores will be affected to each variable over the loop. 6 students, 6
% variables:
for ii = 1 : length(List_of_students)
Init_var_cell_array = cell(nb_fields,1);
assignin('caller', List_of_students{ii}, Init_var_cell_array);
end
Ok, If I stop the script at this point and check for the cell variable "Damien", it is a cell 6x1, like I want.
Question 1) I think it is enough to affirm the cell is pre-allocated! Am I wrong to think so?
%% 2) Get scores data for every student. For the example, I write the code for the first student only (Damien)
for bb = 1: length(List_of_study_fields)
Damien(bb) = Table_Score(bb,2);
end
If I keep running until the end, at this point I get the message:
"The variable Damien appears to change size on every loop iteration (within a script). Consider pre-allocating for speed."
Question 2) So, isn't cell array Damien" correctly preallocated ? or is the array preallocated, but in a way that Code Analyzer does not recognize?
Question 3) Finally, imagine the list of students is very long and the scores table is huge, how could I collect all data in one cell array per student without bothering writing their name systematically?
Could I have something as follows:
for aa = 1:length(List_of_student)
for bb = 1: length(List_of_study_fields)
assign(List_of_student{aa}, Table_Score(bb,aa+1))
end
end
So that in the end all my variables Damien, Michael, etc.. are 6x1 cell array ?
Thank you in advance!
Q1: see comments above - I very rarely need to use assignin - I suspect this could be solved in a better way.
Q2: Preallocating cells is much less important than arrays/matrix because each cell can contain different things so its difficult to preallocate efficiently.
Q3: As mentioned in the comments above, store your data in a dynamic struct:
for aa = 1:length(List_of_student)
for bb = 1: length(List_of_study_fields)
yourData.(List_of_student{aa}).(List_of_study_fields{bb}) = Table_Score(bb,aa+1);
end
end

How to check if an arbitrary number of matlab.unittest.constraints is satisfied by a cell array?

I have a cell array of matlab.unittest.constraints and a cell array of values. I'd like to see if the values match the constraints (respectively). Of course, I can just use a for cycle, something like the following code:
satisfied = zeros(1,argLength);
for i=1:argLength
satisfied(i) = satisfiedBy(cons{i}, val{i});
end;
answer = all(satisfied);
but knowing MATLAB, there must be a way to condense all that into a single line, I just don't know it. I compare the lengths of the arrays beforehand and return false if they're not equal.
Here is a possible CELLFUN statement:
satisfied = cellfun(#satisfiedBy, cons, val);
Make sure satisfiedBy returns only single numeric/logical value.

assigning values to a field of an structure array in MATLAB

I want to replace the value of the fields in a structure array. For example, I want to replace all 1's with 3's in the following construction.
a(1).b = 1;
a(2).b = 2;
a(3).b = 1;
a([a.b] == 1).b = 3; % This doesn't work and spits out:
% "Insufficient outputs from right hand side to satisfy comma separated
% list expansion on left hand side. Missing [] are the most likely cause."
Is there an easy syntax for this? I want to avoid ugly for loops for such simple operation.
Credits go to #Slayton, but you actually can do the same thing for assigning values too, using deal:
[a([a.b]==1).b]=deal(3)
So breakdown:
[a.b]
retrieves all b fields of the array a and puts this comma-separated-list in an array.
a([a.b]==1)
uses logical indexing to index only the elements of a that satisfy the constraint. Subsequently the full command above assigns the value 3 to all elements of the resulting comma-separated-list according to this.
You can retrieve that the value of a field for each struct in an array using cell notation.
bVals = {a.b};
bVals = cell2mat( bVals );
AFAIK, you can't do the same thing for inserting values into an array of structs. You'll have to use a loop.

If a MATLAB function returns a variable number of values, how can I get all of them as a cell array?

I am writing a function to remove some values from a cell array, like so:
function left = remove(cells, item);
left = cells{cellfun(#(i) ~isequal(item, i), cells)};
But when I run this, left has only the first value, as the call to cells{} with a logical array returns all of the matching cells as separate values. How do I group these separate return values into a single cell array?
Also, perhaps there is already a way to remove a given item from a cell array? I could not find it in the documentation.
You have to use () instead of {} to index the cells:
function left = remove(cells, item)
left = cells(cellfun(#(i) ~isequal(item, i), cells));
Using () for indexing will give you a subset of cells, while using {} will return the contents of a subset of cells as a comma-separated list, and only the first entry of that list will get placed in left in your example.
You can check out this MATLAB documentation for more information on using cell arrays.
EDIT: Response to comment...
If you have an operation that ends up giving you a comma-separated list, you can place the individual elements of the list into cells of a cell array by surrounding the operation with curly braces. For your example, you could do:
left = {cells{cellfun(#(i) ~isequal(item, i), cells)}};
The inner set of curly braces creates a comma-separated list of the contents of cells that are not equal to item, and the outer set then collects this list into a cell array. This will, of course, give the same result as just using parentheses for the indexing, which is the more sensible approach in this case.
If you have a function that returns multiple output arguments, and you want to collect these multiple values into a cell array, then it's a bit more complicated. You first have to decide how many output arguments you will get, or you can use the function NARGOUT to get all possible outputs:
nOut = 3; %# Get the first three output arguments
%# Or...
nOut = nargout(#some_fcn); %# Get all the output arguments from some_fcn
Then you can collect the outputs into a 1-by-nOut cell array outArgs by doing the following:
[outArgs{1:nOut}] = some_fcn(...);
It should be noted that NARGOUT will return a negative value if the function has a variable number of output arguments, so you will have to choose the value for nOut yourself in such a case.