How to use inputs in an if statement in matlab - matlab

I'm trying to write a code in MATLAB that has the user input two values. I already have everything written for the input part and I saved the two inputs into two variables: value1 and value2.
What I'm trying to do is use the input values in the matter of:
if value1 = 2
output_result=10
if value1 = 3
output_result=20
and so on.
I've been trying to write an if-elseif statement but I can't seem to figure it out.

Do a switch statement
switch value1
case 2
result = 10;
case 3
result = 20;
...
otherwise
statements
end

If you really want to use an if statement, do this:
if value == 1
result = 10;
elseif value == 2
result = 20;
elseif
%// Put more statements
...
elseif
%// Put even MOAR statements
...
...
else
%// Default case - optional
end
However, the switch statement as per #kkuilla is more elegant. Also note that the else statement is optional. You'd only put this in if everything else fails and want to use a default case.

Related

switch case: go to 'otherwise' from within another case

Is it possible to go from within a case in switch to another case based on a condition?
Here is an example:
flag_1 = 'a'
flag_2 = 1;
x = 0;
switch flag_1
case 'a'
if flag_2 == 1
% go to otherwise
else
x = 1;
otherwise
x = 2;
end
If flag_2 == 1 I want to go from case 'a' to otherwise. Is it possible?
No, this is not possible. There’s no “goto” statement in MATLAB.
One solution is to put the code for the “otherwise” branch into a function, then call that function if your condition is met:
flag_1 = 'a'
flag_2 = 1;
x = 0;
switch flag_1
case 'a'
if flag_2 == 1
x = otherwise_case;
else
x = 1;
otherwise
x = otherwise_case;
end
function x=otherwise_case
% assuming this is more complex of course
x = 2;
end
Similar to Cris' answer, you could set a flag, and have a simpler conditional based on that flag after the switch:
flag_1 = 'a'
flag_2 = 1;
x = 0;
otherwise_case = false;
switch flag_1
case 'a'
if flag_2 == 1
otherwise_case = true;
else
x = 1;
otherwise
otherwise_case = true;
end
if otherwise_case
% assuming this is more complex of course
x = 2;
end
This is simpler if, for instance, the otherwise_case function would have lots of required inputs which are already available in the current scope when using the flag approach instead.
For completeness, I'm going to mention the "early bailout" approach. Basically, you put your switch inside a try/catch:
try
switch flag_1
case 'a'
if flag_2 == 1
throw(...)
else
x = 1;
otherwise
throw(...)
end
catch ME
% otherwise case, if exception is as expected
end
I should note that the other answers are likely more suitable for the present problem. This approach is useful when you have multiple loops or internal functions within the case, and you want to quickly exit all of them and reach the "otherwise". Note that when doing this you should check within the catch clause that the exception is as you expect (example), to avoid legitimate issues that might arise in the cases' logic.

How to return boolean in if else statement and the return value will link to anothe if else statement in Matlab?

I have the following if else statement that created by myself in order to link to the if else statement given in second part:
m=4
if m==3
disp(true)
else
disp(false)
Second part ( this code is fix cannot be change):
if (true)
A=Hello World
else
A=Bye
If using the first part code, my output will be
A=Hello World
but my desire output is
A=Bye
Anyone one have idea to edit the first part, because now my return value in first part not able to link to my second part.
If you can't change the second part's code, I'm afraid your desire cannot be fulfilled. Or rather, I'm afraid your code won't run at all, because your perenthesis, quotes, end-statement (and arguably semicolons) are not in place.
if true
A = 'Hello World';
else
A = 'Bye';
end
This code will return A = 'Hello World', no matter what, since true is always true. If-else conditions work like this:
if (*what's in here evealuates to true*)
%do stuff
else (*if what's up there does not evaluate to true*)
%do other stuff
Clearly, true will always evaluate to true. So the above if-else condition will always return A = 'Hello World'.
You don't need two if statements in order to accomplish this task. One is more than enough to perform all what you need:
m = 4;
if (m == 3)
A = 'Hello World';
else
A = 'Bye';
end
disp(A);
A few comments concerning your code:
if statements need to be closed with an end
if (true) will always pass into the statement
the disp function doesn't assign a value, its only goal is to display it in the Command Window
in order to work with text, you have to enclose it within single quotes ' (char array) or double quotes " (string), more info here
If you posted only small excerpts of your code and you need to perform those two checks sequentially, in different parts of your script, then:
m = 4;
if (m == 3)
m_equals_3 = true;
disp('M == 3');
else
m_equals_3 = false;
disp('M ~= 3');
end
% then, somewhere else...
if (m_equals_3)
A = 'Hello World';
else
A = 'Bye';
end
% ...
I guess this is a homework exercise. You should disclose that if it’s the case.
The exercise requieres you to change the workspace such that the second bit of code evaluated the else case. This can be accomplished by changing the meaning of true. In your first bit of code, make it so that
true = flase;
Or equivalently,
true = 0;
Note that this is really bad form, if you ever do something like this outside of a homework exercise that explicitly asks you to do so, you’ll get fired or maybe even shot. You’ve been warned!
By the way, I assume that the missing quote characters around the strings and the missing ends are typos?

Function with different return variables

Is there a way to have one function that can return two different variables, but only one at a time AND knowing which one is returned in the function call?
example:
I have the following function in which only one of the outputs is valid (the other one would be [])
function [a,b] = AlternatingOutput (input)
if input == 1
return ONLY A
else
return ONLY B
end
end
and i call it in a script
[a,b] = AlternatingOutput (input)
i want a way to say the following (pseudocode):
if (function outputs a)
[a,~] = AlternatingOutput(input)
elseif (function outputs b)
[~,b] = AlternatingOutput(input)
end
the script is run in a loop, and later i need the newest Valid values for a and b, so i cannot overwrite one of the two with []
I do understand that I could just write a function that checks which variable will be output, but I was wondering if there is a more elegant way.
I hope I have made my question clear, and I hope someone can answer me :)
There is no way to tell if an output argument is actually used. You may check the number of output arguments using nargout and it would allow to distinguish between [a] = AlternatingOutput(input) and [~,b] = AlternatingOutput(input)
I don't know the full context of your problem, but maybe you can put all your variables into a struct? Simply pass this struct everytime you call the function and let it decide which variables to manipulate. (This might be slow in some programming languages, but not in matlab).
How about retuning a cell?
function [ ab ] = testfun( input )
if input
ab={'ax'};
else
ab={2};
end
end
No worries about what is in the cell.
thb you could return what ever you want, Matlab does not check the type anyways
If only one of the outputs from the function AlternatingOutput is valid, then you only need to return one output:
function [X] = AlternatingOutput(input)
if input == 1
X = A;
else
X = B;
end
end
To allocate the retured value to either a or b in the loop, put them into a cell:
C = {AlternatingOutput(1), AlternatingOutput(2)};
and then use input to determine which value is change. If input is either 1 or 2 you can just do
for counter = ...
input = mod(input,2)+1;
C{input}=AlternatingOutput(input);
end
If your function doesn't mind accepting more input variables, why not pass a and b as input:
function [a,b] = AlternatingOutput(a,b,input)
if input == 1
a = new_value_for_a;
% b retains its former value
else
% a retains its former value
b = new_value_for_b;
end
end
Then it can be easily called from your script in a loop:
for i= ...
[a,b] = AlternatingOutput(a,b,input);
...
...
end

1-line try/catch equivalent in MATLAB

I have a situation in MATLAB where I want to try to assign a struct field into a new variable, like this:
swimming = fish.carp;
BUT the field carp may or may not be defined. Is there a way to specify a default value in case carp is not a valid field? For example, in Perl I would write
my $swimming = $fish{carp} or my $swimming = 0;
where 0 is the default value and or specifies the action to be performed if the assignment fails. Seems like something similar should exist in MATLAB, but I can't seem to find any documentation of it. For the sake of code readability I'd rather not use an if statement or a try/catch block, if I can help it.
You can make your own function to handle this and keep the code rather clear. Something like:
swimming = get_struct(fish, 'carp', 0);
with
function v = get_struct(s, f, d)
if isfield(s, f)
v = s.(f); % Struct value
else
v = d; % Default value
end
Best,
From what I know, you can't do it in one line in MATLAB. MATLAB logical constructs require explicit if/else statements and can't do it in one line... like in Perl or Python.
What you can do is check to see if the fish structure contains the carp field. If it isn't, then you can set the default value to be 0.
Use isfield to help you do that. Therefore:
if isfield(fish, 'carp')
swimming = fish.carp;
else
swimming = 0;
end
Also, as what Ratbert said, you can put it into one line with commas... but again, you still need that if/else construct:
if isfield(fish,'carp'), swimming = fish.carp; else, swimming = 0;
Another possible workaround is to declare a custom function yourself that takes in a structure and a field, and allow it to return the value at the field, or 0.
function [out] = get_field(S, field)
if isfield(S, field)
out = S.(field);
else
out = 0;
end
Then, you can do this:
swimming = get_field(fish, 'carp');
swimming will either by 0, or fish.carp. This way, it doesn't sacrifice code readability, but you'll need to create a custom function to do what you want.
If you don't like to define a custom function in a separate function file - which is certainly a good option - you can define two anonymous functions at the beginning of your script instead.
helper = {#(s,f) 0, #(s,f) s.(f)}
getfieldOrDefault = #(s,f) helper{ isfield(s,f) + 1 }(s,f)
With the definition
fish.carp = 42
and the function calls
a = getfieldOrDefault(fish,'carp')
b = getfieldOrDefault(fish,'codfish')
you get for the first one
a = 42
and the previous defined default value for the second case
b = 0

Better code for accessing fields in a matlab structure array?

I have a matlab structure array Modles1 of size (1x180) that has fields a, b, c, ..., z.
I want to understand how many distinct values there are in each of the fields. i.e.
max(grp2idx([foo(:).a]))
The above works if the field a is a double. {foo(:).a} needs to be used in the case where the field a is a string/char.
Here's my current code for doing this. I hate having to use the eval, and what is essentially a switch statement. Is there a better way?
names = fieldnames(Models1);
for ix = 1 : numel(names)
className = eval(['class(Models1(1).',names{ix},')']);
if strcmp('double', className) || strcmp('logical',className)
eval([' values = [Models1(:).',names{ix},'];']);
elseif strcmp('char', className)
eval([' values = {Models1(:).',names{ix},'};']);
else
disp(['Unrecognized class: ', className]);
end
% this line requires the statistics toolbox.
[g, gn, gl] = grp2idx(values);
fprintf('%30s : %4d\n',names{ix},max(g));
end
Indeed, there is a better way. Surprisingly, MATLAB allows you to access the struct fields using a key string without eval, for instance:
Models1(1).(names{ix})
so instead, you can write this:
className = class(Models1(1).(names{ix});
...
values = [Models1(:).(names{ix})];
...
values = {Models1(:).(names{ix})};
Also, instead of using class and strcmp, you can just test the same conditions with isa:
v1 = Models1(1).(names{ix});
if (isa(v1, 'double') || isa(v1, 'logical'))
values = [Models1(:).(names{ix})];
% # ...
elseif (isa(v1, 'char'))
values = {Models1(:).(names{ix})};
% # ...
else
disp(['Unrecognized class: ', class(v1)]);
end
It should be much faster.