String not read correctly
3 views (last 30 days)
Show older comments
In the code below, for b = 'AGA' the ouput is c = 'S'. Why isn't the output c = 'R'?
b = 'AGA';
if b=='UUU' | b=='UUC'
c = 'F'
elseif b =='UCU' | b=='UCC' | b=='UCA' | b=='UCG' | b=='AGC' | b=='AGU'
c = 'S'
elseif b =='CGU' | b=='CGC' | b=='CGA' | b=='CGG' | b=='AGA' | b=='AGG'
c = 'R'
end
0 Comments
Accepted Answer
Stephen23
on 12 Sep 2017
Edited: Stephen23
on 12 Sep 2017
Explanation
"...the ouput is c = 'S'. Why isn't the output c = 'R'?"
Because your code does not do what you think it does.
The reason why your code does not work is explained in the documentation, which is why you should always read the documentation for every operation and function that you use. Lets have a look at why your code does not work. The reason why c = 'S' is returned is clearly because the elements of the first elseif condition are all true, exactly as the if documentation states. Lets have a look at the if condition to check:
>> b = 'AGA';
>> b =='UCU' | b=='UCC' | b=='UCA' | b=='UCG' | b=='AGC' | b=='AGU'
ans =
1 1 1
And the reason why the elements are all true is because you decided to use the logical or |, which works element-wise on arrays. In fact only two of the terms are required to get this effect:
>> b=='UCA' | b=='AGC'
ans =
1 1 1
because each of these terms separately gives this:
>> b=='UCA'
ans =
0 0 1
>> b=='AGC'
ans =
1 1 0
and clearly the or of those two vectors is one vector with all true, and thus the first elseif contains only true, and so c = 'S'.
Basically you used the wrong commands, did not bother to read the documentation, and did not check the output from the code that you wrote. These are common mistakes that beginners make: they rely on what they imagine/want/wish/believe their code is doing, and never actually check what the code is really doing. Code cannot read your mind, and does not care about what you want. It is your job to read the documentation and check each line of code to ensure that it is doing exactly what you want.
Better Solutions
MATLAB is a beautiful high-level language, so please do not write ugly code as if this was an ugly low-level language like C++, where everything has to be solved using loops and ifs. As Walter Roberson stated, you should really use strcmp and short-circuit logical operators, or simply use ismember:
b = 'AGA';
if ismember(b,{'UUU','UUC'})
c = 'F';
...
end
or even simpler would be to use switch:
b = 'AGA';
switch b
case {'UUU','UUC'}
c = 'F';
...
end
2 Comments
Guillaume
on 12 Sep 2017
Actually, even better than an endless list of if ... elseif ... or switch ... case ... case ... would be a lookup table, which is also a lot simpler to extend if new conditions need adding:
lut = {'F', {'UUU', 'UUC'}; %output, inputs
'S', {'UCU', 'UCC', 'UCA', 'UCG', 'AGC', 'AGU'}
'R', {'CGU', 'CGC', 'CGA', 'CGG', 'AGA', 'AGG'}};
b = 'AGA'
conditions = [lut{:, 2}]'; %for easier search
outputs = repelem(lut(:, 1), cellfun(@numel, lut(:, 2))) %to match conditions
[found, row] = ismember(b, conditions);
assert(found, 'b not found in look-up table');
c = outputs{row}
Jan
on 14 Sep 2017
+1. The actual question "Why isn't the output c = 'R'?" is explained in this answer and better methods are suggested.
More Answers (2)
Walter Roberson
on 12 Sep 2017
Edited: Walter Roberson
on 12 Sep 2017
You should be using strcmp to compare strings.
You should also consider using ismember
0 Comments
John BG
on 12 Sep 2017
Hi Lmm3
Why not simply using a switch?
b = 'AGA';
switch b
case {'UUU' 'UUC'}
c = 'F';
case {'UCU' 'UCC' 'UCA' 'UCG' 'AGC' 'AGU'}
c = 'S';
case {'CGU' 'CGC' 'CGA' 'CGG' 'AGA' 'AGG'}
c = 'R';
otherwise
c='not defined';
end
Despite the high level compactness of the suggested commands ismember and repelem with the need of defining anonymous functions, such commands end up calling the 'low level' ugly ones that end up doing the hard work. High level functions are passengers carried by low level working functions.
The switch allows an immediate visual inspection of the different logical conditions paired with the expected output.
if you find this answer useful would you please be so kind to consider marking my answer as Accepted Answer?
To any other reader, if you find this answer useful please consider clicking on the thumbs-up vote link
thanks in advance
John BG
3 Comments
John BG
on 12 Sep 2017
To Mr Cobeldick: you suggested a switch but did not write the complete code. Although suggestions may be considered answers, as a matter of fact many are, often a hint is considered a valid answer, a complete working script is usually better appreciated as a valid answer.
You have suggested ismember ad your 1st choice of solution.
This question can be answered with different solutions.
I politely disagree that Lmm3 should consider command switch as the 2nd option.
I started writing my answer with switch in mind, as it is the simple obvious choice. It may be considered primitive, because it's at the same level of if . else, for, and while loops that many times are unreasonably deprecated against more compact ommands that many users need time to learn but it's time they primarily need focussed on achieving a working solution, not a 'beautiful' or 'ugly' one.
MATLAB coherently embraces a really wide range of commands.
Both loops and compact vectoring are equally important.
But not every body has the vectorising skills you have, or are even willing to spend the time learning how to use commands like repelem and cellfun. I am not taking sides here, just stating a fact.
Even more, considering that at the end, it's a rather narrow bunch of ASM commands that, precisely with really elemental operations, end up performing the most elevated and compact MATLAB scripts, I chose switch as the best solution to this question, regardless of whatever you have written.
Regards
John BG
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!