Excel returning a False response - excel

=IF(B12<>"",(IF(U12="Subscription","Subscribe",IF(U12="T.E.H.","Subscribe",IF(U12="ESA","Subscribe",IF(U12="Perpetual","Buy",IF(U12=" "," ")))))))
I get a "False" value in the cell with this formula in it when the value in U12 is not one of the options and I want to get a blank
Appreciate any help
Thanks

Change this: IF(U12=" ", " ") to this: IF(U12=" ", " ", ""). Here's a demo in Google Sheets, but the formulas are the same.
https://docs.google.com/spreadsheets/d/10iFqq0PNt9VhGKMPLCxsI1df0x4nDSxCaCGSdEEktO8/edit#gid=0
However, I don't think this is exactly right. For one thing, it looks like this clause:
IF(U12=" ", " ")
is only there to try to generate the blank you are looking for. If that's the case, then change it to:
IF(U12=" ", " ", "")
However, I think I would probably use some array constants, something like this:
=IF(B12<>"", CHOOSE(SUM(--(U12={"Subscription","T.E.H","ESA"})) + IF(U12="Perpetual", 2) +1, "", "Subscribe", "Buy"))
To break this down a little, let me reformat so it's easier to see:
=IF(
B12 <> "",
CHOOSE(
SUM(--(U12={"Subscription","T.E.H","ESA"})) +
IF(U12="Perpetual", 2) + 1
"", "Subscribe", "Buy"
)
)
I'm going to use CHOOSE, which takes an index number N and a list of choices, and it returns the Nth element in the choice list. To generate the index, I'm going to use a couple of techniques. First look at this:
U12 = {"Subscription", "T.E.H", "ESA"})
This is going to test U12 against all of the choices in the list, and return an array of TRUE/FALSE values. If U12 matches any of the elements in the array constant, then one of those values will be TRUE. We use -- to coerce that array from TRUE/FALSE to 0/1, and then we use SUM to get the array into a single value. It will either be 0 if U12 doesn't match any of the options, or 1 if it does.
Then I'm going to use a standard IF to check if U12 = Perpetual, and return 2 if it does. Adding that result to the previous sum will give us a final number that is either 0, 1 or 2.
CHOOSE is 1 indexed, meaning that it expects the index to be 1 or greater, so we add 1 to the number we just generated and pass it to CHOOSE along with a list of options.
The advantage here is that if the Subscribe options change you can just change the list, instead of having to alter a bunch of nested IFs. Also, if you need to support multiple buy options, you can do it with a similar construction:
SUM(--(U12 = {"Subscription", "T.E.H", "ESA"})) +
IF(SUM(--(U12 = {"Perpetual", "Buy Now"})), 2) + 1
and if you needed to add return values just keep extending:
CHOOSE(
SUM(--(U12 = {"Subscription", "T.E.H", "ESA"})) +
IF(SUM(--(U12 = {"Perpetual", "Buy Now"})), 2) +
IF(SUM(--(U12 = {"Release", "Dropping"})), 3) + 1,
"", "Subscribe", "Buy", "Sell"
)
If you think this is something that might need to be maintained or the options might change, I would set it up like this, as opposed to nested IFs.

Is this a little clearer?
=IF(B12=""," ",IfError(VLookup(U12,{"ESA","Subscribe";"Perpetual","Buy";"Subscription",Subscribe";"T.E.H.","Subscribe"},2,false)," "))
This is really just a table lookup, hence the use of VLookup. The lookup array is a two dimensional array in curly brackets - the commas and semicolons are very important for defining a 2x4 array for VLookup. The IFError function tells how to return your desired " " result if the lookup fails.

Related

how to find two different strings in the same line in matlab

I have a cell obtained from text scan and I want to find the index of lines containing particular string,
fid = fopen('data.txt');
E = textscan(fid, '%s', 'Delimiter', '\n');
and I wanted to know the line numbers (index) of those lines which have a specific text, e.g. I wanted to find the rows that have the keyword "2016":
rows = find(contains(E{1},"2016" );
but I want to find the index of those lines which have two keywords "2016" and "Mathew Perry" (only those lines which have both the keywords).
I tried using this code but does not work
rows = find(contains(E{1},"2016" && contains(E{1},"Mathew Perry");
the error I get is:
Operands to the || and && operators must be convertible to logical scalar values.
To find a single string:
idx = strfind(E{1}, '2016');
idx = find(not(cellfun('isempty', idx)));
Use strfind instead of find. YOu may try the above with and/or. If it works fine, then no problem; if not, get the indices separately for each word and get the intersection of the indices.

Finding indexes of strings in a string array in Matlab

I have two string arrays and I want to find where each string from the first array is in the second array, so i tried this:
for i = 1:length(array1);
cmp(i) = strfind(array2,array1(i,:));
end
This doesn't seem to work and I get an error: "must be one row".
Just for the sake of completeness, an array of strings is nothing but a char matrix. This can be quite restrictive because all of your strings must have the same number of elements. And that's what #neerad29 solution is all about.
However, instead of an array of strings you might want to consider a cell array of strings, in which every string can be arbitrarily long. I will report the very same #neerad29 solution, but with cell arrays. The code will also look a little bit smarter:
a = {'abcd'; 'efgh'; 'ijkl'};
b = {'efgh'; 'abcd'; 'ijkl'};
pos=[];
for i=1:size(a,1)
AreStringFound=cellfun(#(x) strcmp(x,a(i,:)),b);
pos=[pos find(AreStringFound)];
end
But some additional words might be needed:
pos will contain the indices, 2 1 3 in our case, just like #neerad29 's solution
cellfun() is a function which applies a given function, the strcmp() in our case, to every cell of a given cell array. x will be the generic cell from array b which will be compared with a(i,:)
the cellfun() returns a boolean array (AreStringFound) with true in position j if a(i,:) is found in the j-th cell of b and the find() will indeed return the value of j, our proper index. This code is more robust and works also if a given string is found in more than one position in b.
strfind won't work, because it is used to find a string within another string, not within an array of strings. So, how about this:
a = ['abcd'; 'efgh'; 'ijkl'];
b = ['efgh'; 'abcd'; 'ijkl'];
cmp = zeros(1, size(a, 1));
for i = 1:size(a, 1)
for j = 1:size(b, 1)
if strcmp(a(i, :), b(j, :))
cmp(i) = j;
break;
end
end
end
cmp =
2 1 3

Recognize relevant string information by checking the first characters

I have a table with 2 columns. In column 1, I have a string information, in column 2, I have a logical index
%% Tables and their use
T={'A2P3';'A2P3';'A2P3';'A2P3 with (extra1)';'A2P3 with (extra1) and (extra 2)';'A2P3 with (extra1)';'B2P3';'B2P3';'B2P3';'B2P3 with (extra 1)';'A2P3'};
a={1 1 0 1 1 0 1 1 0 1 1 }
T(:,2)=num2cell(1);
T(3,2)=num2cell(0);
T(6,2)=num2cell(0);
T(9,2)=num2cell(0);
T=table(T(:,1),T(:,2));
class(T.Var1);
class(T.Var2);
T.Var1=categorical(T.Var1)
T.Var2=cell2mat(T.Var2)
class(T.Var1);
class(T.Var2);
if T.Var1=='A2P3' & T.Var2==1
disp 'go on'
else
disp 'change something'
end
UPDATES:
I will update this section as soon as I know how to copy my workspace into a code format
** still don't know how to do that but here it goes
*** why working with tables is a double edged sword (but still cool): I have to be very aware of the class inside the table to refer to it in an if else construct, here I had to convert two columns to categorical and to double from cell to make it work...
Here is what my data looks like:
I want to have this:
if T.Var1=='A2P3*************************' & T.Var2==1
disp 'go on'
else
disp 'change something'
end
I manage to tell matlab to do as i wish, but the whole point of this post is: how do i tell matlab to ignore what comes after A2P3 in the string, where the string length is variable? because otherwise it would be very tiring to look up every single piece of string information left on A2P3 (and on B2P3 etc) just to say thay.
How do I do that?
Assuming you are working with T (cell array) as listed in your code, you may use this code to detect the successful matches -
%%// Slightly different than yours
T={'A2P3';'NotA2P3';'A2P3';'A2P3 with (extra1)';'A2P3 with (extra1) and (extra 2)';'A2P3 with (extra1)';'B2P3';'B2P3';'NotA2P3';'B2P3 with (extra 1)';'A2P3'};
a={1 1 0 1 1 0 1 1 0 1 1 }
T(:,2)=num2cell(1);
T(3,2)=num2cell(0);
T(6,2)=num2cell(0);
T(9,2)=num2cell(0);
%%// Get the comparison results
col1_comps = ismember(char(T(:,1)),'A2P3') | ismember(char(T(:,1)),'B2P3');
comparisons = ismember(col1_comps(:,1:4),[1 1 1 1],'rows').*cell2mat(T(:,2))
One quick solution would be to make a function that takes 2 strings and checks whether the first one starts with the second one.
Later Edit:
The function will look like this:
for i = 0, i < second string's length, i = i + 1
if the first string's character at index i doesn't equal the second string's character at index i
return false
after the for, return true
This assuming the second character's lenght is always smaller the first's. Otherwise, return the function with the arguments swapped.

Haskell "let" syntax in a way that it spans multiple rows

Is it possible to write Haskell's "let" statement in a way that it spans multiple rows ?
let a = " something in this row.
something else in this row "
Or else , is there any other way to create a string which spans multiple rows ?
To break up a string literal across multiple lines, use a string break like this:
let a = " something in this row.\
\something else in this row\
\ and more in this row\
\ and yet more in this row "
You put a backslash at the end of each line you want to continue, and then another one at the start of the next line where the text will continue from.
Yes. You can use multiple row expression if you use right indention.
For example,
multiLine = let a = if 1 == 2
then True else False
in a

Matlab - How do I compare two strings letter by letter?

Essentially, I have two strings of equal length, let's say 'AGGTCT' and 'AGGCCT' for examples sake. I want to compare them position by position and get a readout of when they do not match. So here I would hope to get 1 out because there is only 1 position where they do not match at position 4. If anyone has ideas for the positional comparison code that would help me a lot to get started.
Thank you!!
Use the following syntax to get the number of dissimilar characters for strings of equal size:
sum( str1 ~= str2 )
If you want to be case insensitive, use:
sum( lower(str1) ~= lower(str2) )
The expression str1 ~= str2 performs char-by-char comparison of the two strings, yielding a logical vector of the same size as the strings, with true where they mismatch (using ~=) and false where they match. To get your result simply sum the number of true values (mismatches).
EDIT: if you want to count the number of matching chars you can:
Use "equal to" == operator (instead of "not-equal to" ~= operator):
sum( str1 == str2 )
Subtract the number of mismatch, from the total number:
numel(str1) - sum( str1 ~= str2 )
You can compare all the element of the string:
r = all(seq1 == seq2)
This will compare char by char and return true if all the element in the resulting array are true. If the strings can have different sizes you may want to compare the sizes first. An alternative is
r = any(seq1 ~= seq2)
Another solution is to use strcmp:
r = strcmp(seq1, seq2)
Just would like to point out that you are asking to calculate the hamming distance (as you ask for alternatives - the article contains links to some). This is already discussed here. In short the builtin command pdist can do it.

Resources