Matlab name assignment - matlab

I am trying to decrease some big chucks of matlab code i had from a while ago, and was hoping to get them a bit more "clean".
The VarName2,VarName3,VarName4 ...etc are provide by measured data and i will know what they are always going to be thus i gave me the name A,B ,C , the think i want changed though is the first part of the name, so every time i run the .m file I will use the input('') option
where as fname = 'SWAN' and A, B , C are the second part of the name and they are constant.
fname = input ('enter name')
fname_A = VarName2
fname_B = VarName3
fname_C = VarName4
and want to be getting
SWAN_A = VarName2
SWAN_B = VarName3
SWAN_C = VarName4
thank you
Following your advices I been trying the structure construction
S.name = input ('enter name of the data ".." ==')
S.A = A;
S.A(1,:)=[];
S.B = B;
S.B(1,:)=[];
S.C = C;
S.C(1,:)=[];
S.D = D;
S.D(1,:)=[];
S.E = E;
S.E(1,:)=[];
may i ask if i can also have an input thing command so i can change the name of the structure?
Precede the script with S='west' and then do
'S'.name = input ('enter name of the data ".." ==')
S.A = A;

Here is how I would probably store the information that you are handling:
S.name = input ('enter name')
S.A = VarName2
S.B = VarName3
S.C = VarName4
And if you want to do it a few times:
for t=3:-1:1
S(t).name = input ('enter name')
S(t).A = VarName2
S(t).B = VarName3
S(t).C = VarName4
end
In this way you could now find the struct named 'swan':
idx = strcmpi({S.name},'SWAN')

you can use eval
eval( sprintf('%s_A = VarName2;', fname ) );
eval( sprintf('%s_B = VarName3;', fname ) );
eval( sprintf('%s_C = VarName4;', fname ) );
Note that the use of eval is not recommended.
One alternative option may be to use struct with dynamic field names:
A.( fname ) = VarName2;
B.( fname ) = VarName3;
C.( fname ) = VarName4;
Now you have three structs (A, B and C) with A.SWAN equal to VarName2, B.SWAN equal to VarName3 etc.

Related

How do I define a variable from another function?

I have a multi-fuction script that is supposed to ask the user for 4 different cars and weigh them based on ratings to give the user the best car to purchase.
What I want to do is have a prompt for every car the user inputs so the user can put in data for each variable the user decides to use. However, when titling the prompt I want to use the cars name in the prompt. It seems impossible to me and Im not sure what to do, im very new to coding.
Main Script
prompt1 = {'How Many Cars (4): '};
title1 = 'Cars';
answer1 = inputdlg(prompt1, title1, [1 40]);
Q1 = str2double(answer1{1});
[N] = Group_Function1(Q1);
Car1 = N(1); %Stores the names of the cars
Car2 = N(2);
Car3 = N(3);
Car4 = N(4);
prompt2 = {'How Many Variables (4): '};
title2 = 'Variables';
answer2 = inputdlg(prompt2, title2, [1 50]);
fprintf('This code can accept costs between 0-100000\n');
fprintf('This code can accept top speeds between 0-200\n');
fprintf('This code can also accept the terms none, some, & alot\n');
fprintf('This code can accept safety ratings between 0-5\n');
Q2 = str2double(answer2{1});
[V,W] = Group_Function2(Q2);
W1 = W(1); %Stores the weights of the varibles
W2 = W(2);
W3 = W(3);
W4 = W(4);
for h=1:Q1
[H] = Group_Function3(V);
Weights(h,:)=H;
end
Group_Function1
function [N] = Group_Function1(Q1)
for Q = 1:Q1
prompt = {'Name of Car:'};
title = 'Car Name';
answer = inputdlg(prompt,title, [1 80])';
N(Q) = answer(1);
end
Group_Function2
function [V,W] = Group_Function2(Q2)
for Q=1:Q2
prompt = {'Variable? (Negative Variables First):','weights in decimal
form?'};
title = 'Variables and Weights';
answer = inputdlg(prompt,title, [1 80])';
V(Q)=answer(1);
W(Q)=str2double(answer{2});
s=sum(W);
end
if s~=1
fprintf('Weights do not add up to 1. Try Again!\n');
Group_Function2(Q2);
end
end
Group_Function3 (Where the problem occurs)
function [H] = Group_Function3(V)
prompt = {V};
title = ['Variable Ratings For' Group_Function1(answer{1})];
h = inputdlg(prompt, title, [1 80])';
end
The Problem
For 'Group_Function3' I want the prompt to include the users inputs from 'Group_Function1' so that when the prompt comes up to input the answers I know which vehicle I am entering for.
Each function runs in its own workspace, it means it does not know the state or content of variables outside of it. If you want a function to know something specific (like the name of a car), you have to give that to the function in the input parameters. A function can have several inputs parameters, you are not limited to only one.
Before going into the Group_Function3 , I'd like to propose a new way for Group_Function1.
Group_Function1 :
You run a loop to ask independantly for each car name. It is rather tedious to have to validate each dialog boxe. Here is a way to ask for the 4 car names in one go:
replace the beginning of your script with:
title1 = 'Cars';
prompt1 = {'How Many Cars (4): '};
answer1 = inputdlg(prompt1, title1 );
nCars = str2double( answer1{1} );
CarNames = getCarNames(nCars) ; % <= use this function
% [N] = Group_Function1(Q1); % instead of this one
and replace Group_Function1 with:
function CarNames = getCarNames(nCars)
title = 'Car Names';
prompt = cellstr( [repmat('Name of car #',nCars,1) , sprintf('%d',(1:nCars)).'] ) ;
CarNames = inputdlg( prompt, title, [1 80] ) ;
end
Now CarNames is a cell array containing the name of your 4 cars (as your variable N was doing earlier. I recommend sligthly more explicit variable names).
You can run the rest of your code as is (just replace N with CarNames, and Q1 with nCars).
Group_Function3 :
when you get to the Group_Function3, you have to send the current car name to the function (so it can use the name in the title or prompt). So replace your Group_Function3 as following (we add an input variable to the function definition):
function H = Group_Function3( V , thisCarName )
prompt = {V};
title = ['Variable Ratings For' thisCarName];
H = inputdlg(prompt, title, [1 80])';
end
and in your main script, call it that way:
for h = 1:nCars
thisCarName = carNames{h} ;
H = Group_Function3( V , thisCarName ) ;
% ...
% anything else you want to do in this loop
end

How to generalize Matlab function?

I have a Matlab function. I need to generalize this function. This code’s aim is to check this IndicMPs are in the TableTemp, if it is there, then we extract relevant age limits, such as: Age_Limite_DC, Age_Limite_IT, Age_Limite_Ch and Transfert_Prime_IT_DC. My idea is to generalize, passing parameters to find out the "Type_pret" is.(May be I'm wrong) Since I'm beginner to Matlab can someone help me to encode a more generic function that can be used in a more general context?
function Structure = optimisation_function()
Data = load('Data.mat');
Structure = Data.Structure;
TableTemp = Data.TableTemp;
Age_Limite_DC = zeros(size(Structure,1),1);
Age_Limite_IT = zeros(size(Structure,1),1);
Age_Limite_CH = zeros(size(Structure,1),1);
Transfert_Prime_IT_DC = zeros(size(Structure,1),1);
for IndexMPAL = 1 : length(Structure.AnneeSouscription)
% Determine Type_Pret (Loan Type)
if ~isempty(strfind(Structure.Type_Pret{IndexMPAL},'A'))
Type_Pret = 'A';
elseif ~isempty(strfind(Structure.Type_Pret{IndexMPAL},'B'))
Type_Pret = 'B';
elseif ~isempty(strfind(Structure.Type_Pret{IndexMPAL},'C'))
Type_Pret = 'C';
elseif ~isempty(strfind(Structure.Type_Pret{IndexMPAL},'D'))
Type_Pret = 'D';
elseif ~isempty(strfind(Structure.Type_Pret{IndexMPAL},'E'))
Type_Pret = 'E';
end
MP_CP = Structure.NomCodeProduit(IndexMPAL);
MP_AnSous = Structure.AnneeSouscription(IndexMPAL);
MP_TypePret = Type_Pret;
IndicCP = strcmp(MP_CP, TableTemp.CodeProduit);
IndicAS = MP_AnSous== TableTemp.AnneeSouscription;
IndicTP = strcmp(MP_TypePret, TableTemp.TypePret);
IndicMP = IndicCP & IndicAS & IndicTP;
if ~any(IndicMP)
Msg = strcat('CodeProduct:',MP_CP{1}, ', Année Souscription:', num2str(MP_AnSous), ', Type Prêt:', MP_TypePret);
error('Error', Msg)
else
Age_Limite_DC(IndexMPAL,1) = TableTemp.Age_Limite_DC(IndicMP,1);
Age_Limite_IT(IndexMPAL,1) = TableTemp.Age_Limite_IT(IndicMP,1);
Age_Limite_CH(IndexMPAL,1) = TableTemp.Age_Limite_CH(IndicMP,1);
Transfert_Prime_IT_DC(IndexMPAL,1)=
TableTemp.Transfert_Prime_IT_DC(IndicMP,1);
end
end
Structure.Age_Limite_DC = Age_Limite_DC;
Structure.Age_Limite_IT = Age_Limite_IT;
Structure.Age_Limite_CH = Age_Limite_CH;
Structure.Transfert_Prime_IT_DC = Transfert_Prime_IT_DC;
end
The if/elseif can be simplified with a cell array:
liststr = {'A','BB','C','D','E'}; % builds a cell array, each cell contains a string
Positive_matches = strfind(liststr,Structure.Type_Pret{IndexMPAL}) % returns a list for each cell of the indices where the element was found (empty if none)
Index = find(~cellfun('isempty', Positive_matches )) % converts the previous list into a logical 0/1 array indicating whether an item was found (1) or not (0)
% if isempty(Index); continue; end % If no index is found, to avoid an error in the next instruction, skips the rest of the code.
Type_Pret = liststr(Index(1));
If the Type_Pret are the same in your list and in Structure? , you can usestrcmp`:
liststr = {'A','B','C','D','E'};
if any(strcmp(Structure.Type_Pret,liststr))
Type_Pret = Structure.Type_Pret
else
% handle error
end
You can also work directly on Structure.Age_Limite_DC without using Age_Limite_DC.

Ini file read and write + add new property + matlab [duplicate]

This question already has an answer here:
Property_value + matlab
(1 answer)
Closed 9 years ago.
How to read and write ini files: I want to add new property to an existing one. I want to write the ini file to temp file and finally add the new property to it. the new property will have head,name,desc, value and layout (like: line 1 & 3)
#---------------
# head
# --------------
[name]% type
# desc
value
fileData = [];
fh = fopen( fileName, 'r' ); % read handle
tname=tempname();
wfh =fopen(tname,'w'); % write handle
line = fgetl(fh);
val = '';
Prop ='';
type = '';
header = '';
desc= '';
while ischar(line)
if strcmpi(line(1),'#') && strcmpi(line(3),'=')
layout = line(2:end);
elseif strcmpi(line(1),'#')&& ~strcmpi(line(3),'=')
header = line(2:end);
else
Prop = regexp(line,{'\[*\w+\]\s*%\s*.*\s*'},'match');
[property data_type] = strtok(Prop,'%')
prop_p = property{1};% property_name
prop_per = regexprep(prop_p,{'\[','\]'},'');
prop = prop_per{1};
Dtype = data_type{1}; % datatype
dtype = strtrim(strrep(Dtype,'%',''));
DATA_type = dtype{1};
end
% How can i define filedname (prop) for the 'layout' and 'header' as they are found in lines before the actual'prop'.
% From command window
% Undefined variable prop.
% Error in ecco2511>add (line 212)
% fileData.(prop{1}).layout = layout;
desc = fgetl(fh); % description
desc = desc(1:end);
line = fgetl(fh);
val = line(1:end);
fileData.(prop).layout = layout;
fileData.(prop).header = header;
fileData.(prop).type = DATA_type;
fileData.(prop).desc = desc;
fileData.(prop).val = val;
line = fgetl(fh); % keep reading
end
if ~isfield( fileData, propName)
fileData.(propName).val = newVal;
fileData.(propName).type = datatype;
fileData.(propName).desc = description;
fileData.(propName).layout = layout;
fileData.(propName).header = header;
else
error ( 'property %s already exists, use set to change its value',propName );
end
fileData = orderfields( fileData );
propNames = fieldnames( fileData );
for ii = 1:numel( propNames )
fprintf(wfh,'%s\r',fileData.(propNames{ii}).layout);
fprintf(wfh,'\n');
fprintf(wfh,'%s\r',fileData.(propNames{ii}).header);
fprintf(wfh,'\n');
fprintf(wfh,'%s\r',fileData.(propNames{ii}).layout);
fprintf(wfh,'\n');
fprintf( wfh, '[%s]%s\r', (propNames{ii}),fileData.(propNames{ii}).type);
fprintf(wfh,'\n');
fprintf( wfh,'#%s\r',fileData.(propNames{ii}).desc);
fprintf(wfh,'\n');
fprintf( wfh,'%s\r',fileData.(propNames{ii}).val);
fprintf(wfh,'\n');
end
fclose(fh);
fclose(wfh);
[status,errmsg]= movefile(tname,fileName,'f');
Sounds like you need INI Config from MATLAB File Exchange. It will allow you to read, write, and modify INI style files. I have used it a number of times and it works quite well.

nested for loop query

I am trying to do something rather simple, but can't seem to get it...
I have 3 cell-arrays with strings,
A = {'ConditionA'; 'ConditionB'; 'ConditionC'; 'ConditionD'};
B = {'Case1'; 'Case2'; 'Case3'; 'Case4'};
C = {'Rice'; 'Beans'; 'Carrots'; 'Cereal';'Tomato'; 'Cabbage';...
'Sugar'}
I want to produce a vector with the concatenated (strcat?) combinations, as it this were a "tree diagram", like:
strcat(A(1),B(1),C(1))
strcat(A(1),B(1),C(2))
strcat(A(1),B(1),C(3))
strcat(A(1),B(1),C(4))
strcat(A(1),B(1),C(5))
strcat(A(1),B(1),C(6))
strcat(A(1),B(1),C(7))
strcat(A(1),B(2),C(1))
So what the first elements I am trying to get are (in a column ideally):
ConditionACase1Rice
ConditionACase1Beans
ConditionACase1Carrots
ConditionACase1Cereal
ConditionACase1Tomato
ConditionACase1Cabbage
ConditionACase1Sugar
ConditionACase2Rice
etc etc etc...
I know that:
for i=1:length(A)
E(i) = strcat(A(i),B(1),C(1))
end
Works for one "level". I have tried:
for i=1:length(A)
for j=1:length(B)
for k=1:length(C)
P(i) = strcat(A(i),B(j),C(k));
end
end
end
But this doesn't work...
I would be really grateful if I could be helped with this.
Thanks in advance!
From what I understood, you want all possible combinations of the strings of the input arrays as specified. If so, simply replace your nested loops with the following:
P = cell(length(A)*length(B)*length(C),1);
t=1;
for i=1:length(A)
for j=1:length(B)
for k=1:length(C)
P(t) = strcat(A(i),B(j),C(k));
t = t+1;
end
end
end
For the input arrays,
>> A = {'ConditionA'; 'ConditionB'; 'ConditionC'; 'ConditionD'};
>> B = {'Case1'; 'Case2'; 'Case3'; 'Case4'};
>> C = {'Rice'; 'Beans'; 'Carrots'; 'Cereal';'Tomato'; 'Cabbage';'Sugar'};
The value of P would be:
>> P
P =
'ConditionACase1Rice'
'ConditionACase1Beans'
'ConditionACase1Carrots'
'ConditionACase1Cereal'
'ConditionACase1Tomato'
'ConditionACase1Cabbage'
'ConditionACase1Sugar'
'ConditionACase2Rice'
'ConditionACase2Beans'
'ConditionACase2Carrots'
'ConditionACase2Cereal'
'ConditionACase2Tomato'
'ConditionACase2Cabbage'
'ConditionACase2Sugar'
'ConditionACase3Rice'
'ConditionACase3Beans'
'ConditionACase3Carrots'
'ConditionACase3Cereal'
'ConditionACase3Tomato'
'ConditionACase3Cabbage'
'ConditionACase3Sugar'
'ConditionACase4Rice'
'ConditionACase4Beans'
'ConditionACase4Carrots'
'ConditionACase4Cereal'
'ConditionACase4Tomato'
'ConditionACase4Cabbage'
'ConditionACase4Sugar'
'ConditionBCase1Rice'
'ConditionBCase1Beans'
'ConditionBCase1Carrots'
'ConditionBCase1Cereal'
'ConditionBCase1Tomato'
'ConditionBCase1Cabbage'
'ConditionBCase1Sugar'
'ConditionBCase2Rice'
'ConditionBCase2Beans'
'ConditionBCase2Carrots'
'ConditionBCase2Cereal'
'ConditionBCase2Tomato'
'ConditionBCase2Cabbage'
'ConditionBCase2Sugar'
'ConditionBCase3Rice'
'ConditionBCase3Beans'
'ConditionBCase3Carrots'
'ConditionBCase3Cereal'
'ConditionBCase3Tomato'
'ConditionBCase3Cabbage'
'ConditionBCase3Sugar'
'ConditionBCase4Rice'
'ConditionBCase4Beans'
'ConditionBCase4Carrots'
'ConditionBCase4Cereal'
'ConditionBCase4Tomato'
'ConditionBCase4Cabbage'
'ConditionBCase4Sugar'
'ConditionCCase1Rice'
'ConditionCCase1Beans'
'ConditionCCase1Carrots'
'ConditionCCase1Cereal'
'ConditionCCase1Tomato'
'ConditionCCase1Cabbage'
'ConditionCCase1Sugar'
'ConditionCCase2Rice'
'ConditionCCase2Beans'
'ConditionCCase2Carrots'
'ConditionCCase2Cereal'
'ConditionCCase2Tomato'
'ConditionCCase2Cabbage'
'ConditionCCase2Sugar'
'ConditionCCase3Rice'
'ConditionCCase3Beans'
'ConditionCCase3Carrots'
'ConditionCCase3Cereal'
'ConditionCCase3Tomato'
'ConditionCCase3Cabbage'
'ConditionCCase3Sugar'
'ConditionCCase4Rice'
'ConditionCCase4Beans'
'ConditionCCase4Carrots'
'ConditionCCase4Cereal'
'ConditionCCase4Tomato'
'ConditionCCase4Cabbage'
'ConditionCCase4Sugar'
'ConditionDCase1Rice'
'ConditionDCase1Beans'
'ConditionDCase1Carrots'
'ConditionDCase1Cereal'
'ConditionDCase1Tomato'
'ConditionDCase1Cabbage'
'ConditionDCase1Sugar'
'ConditionDCase2Rice'
'ConditionDCase2Beans'
'ConditionDCase2Carrots'
'ConditionDCase2Cereal'
'ConditionDCase2Tomato'
'ConditionDCase2Cabbage'
'ConditionDCase2Sugar'
'ConditionDCase3Rice'
'ConditionDCase3Beans'
'ConditionDCase3Carrots'
'ConditionDCase3Cereal'
'ConditionDCase3Tomato'
'ConditionDCase3Cabbage'
'ConditionDCase3Sugar'
'ConditionDCase4Rice'
'ConditionDCase4Beans'
'ConditionDCase4Carrots'
'ConditionDCase4Cereal'
'ConditionDCase4Tomato'
'ConditionDCase4Cabbage'
'ConditionDCase4Sugar'
Let me know if you need further assistance.
I am not really familiar with matlab.. but maybe try something like this?
for A = {'ConditionA'; 'ConditionB'; 'ConditionC'; 'ConditionD'};
for B = {'Case1'; 'Case2'; 'Case3'; 'Case4'};
for C = {'Rice'; 'Beans'; 'Carrots'; 'Cereal';'Tomato'; 'Cabbage'; 'Sugar'}
P(i) = strcat(A(i),B(j),C(k));
end
end
end
{
x = 1;
for i=1:length(A)
for j=1:length(B)
for k=1:length(C)
P(x) = strcat(A(i),B(j),C(k));
x = x + 1;
end
end
end
}
Please basically check your code before posting to PO as this is a very simple debugging

How to sort property -value pair in alphabetical order with Matlab

I want to add a property-value pair to existing file. In the mean time all the properties should be ordered in alphabetical order. For example :
[Info] % property 1
value 1
[system] % property 2
value 2
How can i add additional property such that all properties will be sorted in alphabetical order. I was able to add property -value pair to the end of the file using
fh = fopen(filename,'a') but i am not able to sort them alphabetically.
so far i tried this as follows but with this one it keeps printing only the new property-value pair . I want to print remaining properties onces it prints the new one.
function [] = myfun(filename ,propName,propvalue)
rfh = fopen(filename,'r');
tname = tempname();
wfh = fopen(tname,'w');
line = fgetl(rfh);
while ischar(line)
if (line(1) == '[') && (line(end) == ']')
property = lower(line(2:end-1)) % from ini file
String2 = property;
String1 = propName;
[sat] = sor(String1,String2)% subfunction
if sat == -1
fprintf(wfh,'[%s]\r\n%s\r\n',propName,propvalue);
else
fprintf(wfh,'%s\r\n',line);
end
else
fprintf(wfh,'%s\r\n',line);
end
line = fgetl(rfh);
end
fclose(rfh);
fclose(wfh);
movefile(tname,filename,'f')
function [sat] = sor(String1,String2)
Index = 1;
while Index < length(String1) && Index < length(String2) && String1(Index) == String2(Index)
Index = Index + 1;
end
% Return the appropriate code
if String1(Index) < String2(Index)
sat= -1
elseif String1(Index) > String2(Index)
sat= +1
else % the characters at this position are equal -- the shorter of the two strings should be "less than"
if length(String1) == length(String2)
sat = 0
elseif length(String1) < length(String2)
sat = -1
else
sat = +1
end
end
Is this a .ini file? You might want to take a look at INIConfig from the MATLAB File Exchange, a set of routines for handling INI files arranged in a convenient class. I haven't used it, but perhaps it might do what you need.
If not, you can always:
Read in the file
Loop through it line by line
When you find a line starting with [ followed by a word alphabetically later than the property you'd like to insert, insert your property and value
Include the remainder of the file
Write the whole file back out again.
How about read the file into a struct?
function fileData = readFileIntoStruct( fileName )
%
% read [property] value pairs file into struct
%
fh = fopen( fileName, 'r' ); % read handle
line = fgetl( fh );
while ischar( line )
% property
tkn = regexp( line, '\[([^\]+)]\]', 'once', 'tokens' );
% read next line for value
val = fgetl( fh );
fileDate.(tkn{1}) = val;
line = fgetl( fh ); % keep reading
end
fclose( fh ); % don't forget to close the file at the end.
Now you have all the data as a struct with properties as fieldnames and values as the field value.
Now you can update a property simply by:
function fileData = updateProperty( fileData, propName, newVal )
if isfield( fileData, propName )
fileData.(propName) = newVal;
else
warning( 'property %s does not exist - please add it first', propName );
end
You can add a property:
function fileData = addProperty( fileData, propName, newVal )
if ~isfield( fileData, propName )
fileData.(propName) = newVal;
else
warning ( 'property %s already exists, use update to change its value', propName );
end
You can sort the properties alphabetically using orderfields:
fileData = orderfields( fileData );
You can write the struct back to file simply using:
function writeDataToFile( newFileName, fileData )
fopen( newFileName , 'w' ); %write handle
propNames = fieldnames( fileData );
for ii = 1:numel( propNames )
fprintf( fh, '[%s]\r\n%s\r\n', propNames{ii}, fileData.(propNames{ii}) );
end
fclose( fh );
Assumptions:
The properties' names are legitimate Matlab field names (see variable naming for details).
The value of each property is always a string.
I did not include any error-checking code in these examples (files not found, wrongly formatted strings, etc.)
I assume the input file is strictly "[prop] val" pairs without any additional comments etc.