Applying the command unique and lower on a variable - matlab

I currently having a script in matlab that creates a cell array that holds all the terms in a document. I need to use the command unique and lower on the variable to avoid duplicates. I can't work out how to place this on the variable.
Mylist = [];
for C = 1:length(docs)
list = tokenize(docs{C}, ' .,-');
Mylist = [Mylist; list];
end

I create a new variable and used unique and lower on the current cell array.
Newlist = unique(lower(list));
My final code is
Mylist = [];
for C = 1:length(docs)
list = tokenize(docs{C}, ' .,()"%-+/');
Newlist = unique(lower(list));
Mylist = [Mylist; Newlist];
end

Related

What is the best practice to recursively extract data from a nested structure in matlab?

I'm trying to exctract some data from a nested structure in a recursive manner. First, I know that this has a field (values) which repeats itself inside the nested structure. Secondly I know that the structure which has those values has only structures as fields. In the below code I've tried to acces the structure.values by searching if my current structure has a field named values. If it has, I put .values at the end of my structure name. If it doesn't have this field, I verify if all the fields are structures. If they are, it means that I will have to consider them further and to extract the values from each one. If the fields are not structures, it means that they are values and I save them into a new simplified structure. Example of fields that I want: S.values.model1.values.mission.values.(alt/list). Currently, with the below code I'm only able to get the values from one field and then I get an error and don't know how to approach further.
Code example:
clear all
clc
S=struct()
S.case='1';
S.type='A';
S.values.model1.case='2'
S.values.model1.type='C'
S.values.model1.values.mission.case='3'
S.values.model1.values.mission.type='D'
S.values.model1.values.mission.values.alt='none'
S.values.model1.values.mission.values.list=2
S.values.model1.values.mission.values.parameter=4
S.values.model1.values.phase.case='4'
S.values.model1.values.phase.type='A'
S.values.model1.values.phase.values.num='all'
S.values.model1.values.phase.values.eq=2
S.values.model1.values.phase.values.unit=4
S.values.model1.values.analysis.case='1'
S.values.model1.values.phase.type='A'
S.values.model1.values.phase.values.nump1.list='all'
S.values.model1.values.phase.values.nump1.table='four'
S.values.model1.values.phase.values.nump1.mean=0
S.values.model1.values.phase.values.nump2.list='none'
S.values.model1.values.phase.values.nump2.table='three';
S.values.model1.values.phase.values.nump2.mean=1
s=S.values.model1;
names=fieldnames(s);
nnames=numel(names);
newStruct={};
[valsi,newstructi]=extractValues(names,s,nnames,newStruct)
function [vals,newStruct]=extractValues(names,vals,nnames,newStruct)
if any(strcmp(names,'values'))
vals=vals.('values');
names=fieldnames(vals)
nnames=numel(names)
[vals,newStruct]=extractValues(names,vals,nnames,newStruct);
end
for j=1:nnames
value(j)=isstruct((vals.(names{j})));
end
if all(value)
for k=1:nnames
vals=(vals.(names{k}));
names=fieldnames(vals);
nnames=numel(names);
[vals,newStruct]=extractValues(names,vals,nnames,newStruct);
end
else
for j=1:nnames
value=(vals.(names{j}));
newStruct.(names{j})=value;
end
end
end
As it is known beforehand what fields are requested you can arrange the subsequent filed names in a cell array and use a loop to extract the value:
names = {'values', 'model1', 'values', 'mission', 'values', 'alt'};
out = S;
for name : names
out = out.(name{1});
end
So that is a loop version of using:
out = S.values.model1.values.mission.values.alt;
EDIT:
If you want to list all field names and all field values you can used these functions:
function out = names(s, p)
if isstruct(s)
out = {};
f = fieldnames(s);
for i = 1:numel(f)
s1 = s.(f{i});
p1 = [p '.' f{i}];
out = [out; names(s1, p1)];
end
else
out = {p};
end
end
function out = values(s)
if isstruct(s)
out = {};
f = fieldnames(s);
for i = 1:numel(f)
out = [out; values(s.(f{i}))];
end
else
out = {s};
end
end
Use them as:
n = names(S, 'S');
v = values(S);

Associate two different variables in a cell array

Let's say I have a cell c_infos <1x313 cell>, that contains (among others) a name associated to a node_ID. c_infos{1,i}.node_ID and c_infos{1,i}.name. I want to create a matrix that for each node_ID, we do have all the associated names.
I started with:
function [] = displayNodeCusts (c_infos)
list = [] ;
for i = 1:length(c_infos)
for j = 1:length(c_infos)
if c_infos{1,i}.node_ID == c_infos{1,j}.node_ID
list(end+1) = c_infos{1,j}.name
end
end
end
end
But then I don't know which node is associated to the names.
You can use a function called cellfun which will perform the same task in all of the cells within your variable. By doing this, you can pull out all of the names without having to use for loops. I wrote some code as an example. Hope this helps.
listofnames = cellfun(#(x) x.name,c_infos,'UniformOutput',false);
uniquefromlist = unique(listofnames);
for aa = 1:length(uniquefromlist)
allrelevantentries = strcmp(uniquefromlist{aa},listofnames);
storage{aa} = {c_infos{allrelevantentries}};
end

How to extract file names in a loop into a character array?

I have a code like below. I want to generate an array with all the file names and combine with the data that I collected from each file.
DataCC = dir('*-CC.xls'); %select the file type
MeanAreaCC=[];
PlateNameCC=[];
for w = 1: numel(DataCC)
basefilenamedata=DataCC(w).name; %extract the file name
T=readtable(basefilenamedata); %read table in
PlateNameCC=[PlateNameCC basefilenamedata]; %generate the file name array
MeanAreaCC = [MeanAreaCC mean(T.Area)]; %generate the data array
end
x=array2table([PlateNameCC, transpose(MeanAreaCC)],'VariableNames',{'Iso-Condi-Rep','MeanAreaCC'}); %combine two arrays just generated
writetable(x,fullfile(DataFolder,'DataSummary.xls'),'Sheet',1,'Range','A1');
But my code didn't work, as the PlateNameCC is generated as one character but not an array. This came to an error complaining different array size, when I combine PlateNameCC with MeanAreaCC. Could somebody check it for me? Thank you!
There are a couple things wrong here.
First, PlateNameCC = [PlateNameCC basefilenamedata]; is going to create one long string of garbage.
For example:
fnames = dir('*.m')
namelist = [];
for ii = 1:numel(fnames)
namelist = [namelist fnames(ii).name]
end
Gives me:
namelist =
'SOcode.mcallbacksclass.mtestcode.m'
You want to use a string array or a cell array:
fnames = dir('*.m');
namelist1 = string({fnames.name});
namelist2 = {fnames.name};
Which returns:
namelist1 =
1×3 string array
"SOcode.m" "callbacksclass.m" "testcode.m"
namelist2 =
1×3 cell array
{'SOcode.m'} {'callbacksclass.m'} {'testcode.m'}
Second, there's no point trying to concatenate two (very) unlike arrays to create a table when you can just use the table constructor itself:
fnames = dir('*.m');
namelist = string({fnames.name});
data = [1, 2, 3];
T = table(namelist.', data.');
Which gives:
T =
3×2 table
Var1 Var2
__________________ ____
"SOcode.m" 1
"callbacksclass.m" 2
"testcode.m" 3

Creating variable from other variables in MATLAB: code with reproduction

I have a question regarding this type of code:
First = ["A","B","C"];
Second = ["D","E","F"];
Group = ["First", "Second"];
for gr = Group
current = gr;
for number = 1:numel(current)
my_variable(number) = current(number);
end
end
That's the reproduction of my problem. In this case my_variable is equal to "First" for example. But I wanted it to be "A" then "B" then "C" from variable named "First".
For my understanding this code should do the following:
1st step: for gr = Group means gr = First to Second
2nd step: current = gr; means current = First
3rd step: for number = 1:numel(current) means number = 1:3 (number of elements in "First")
4th step: my_variable(number) = current(number); means my_variable = First(1) = "A"
Instead of that I get my variable equal to "First" or "Second".
I hope you understand what I mean.
P.S. the string arrays I'm using with double quotes (" ") like First = ["A","B","C"]; are only available in Matlab 2016b or later.
You should use cell arrays to do this:
first = {'A','B','C'};
second = {'D','E','F'};
group = {first, second};
for group_ind = 1:numel(group)
current = group{group_ind};
my_variable = cell(1,numel(current));
for number = 1:numel(current)
my_variable{number} = current{number};
disp(my_variable)
end
end
For first and second, you can also use the string arrays:
first = ["A","B","C"];
second = ["D","E","F"];
group = {first, second};
for group_ind = 1:numel(group)
current = group{group_ind};
my_variable = strings(1,numel(current));
for number = 1:numel(current)
my_variable(number) = current(number);
disp(my_variable)
end
end

Removing items from a structure array in matlab

I have a very large structure array in matlab. Suppose, for argument's sake, to simplify the situation, I have something like:
structure(1).name = 'a';
structure(2).name = 'b';
structure(3).name = 'c';
structure(1).returns = 1;
structure(2).returns = 2;
structure(3).returns = 3;
Now suppose I have some condition that comes along and makes me want to delete everything from structure(2) (any and all entries in my structure array). What is a good way to do that?
My solution has been to just set the corresponding fields to [] (e.g. structure(1).name = [];), but that doesn't remove them, that only makes them empty. How do I actually remove them completely from the structure array? Is there a way?
simple if you want to delete element at index i do the following:
i = 3
structure(i) = [];
And that will remove element at index 3.
Example:
st.name = 'text';
st.id = 1524;
arrayOfSt = [st st st st st];
Now:
arrayOfSt =
1x5 struct array with fields:
name
id
If we execute:
arrayOfSt(2) = [];
then the new value of the array of structers will be:
arrayOfSt =
1x4 struct array with fields:
name
id
Try it !