Confusion about If statement output in my MATLAB code using contains() - matlab

Apologies if a similar question has already been asked.
I am trying to compare two lists of company names and have created a sequence of if statements within a for loop, with a contains() function in the if statements.
The logic is that for each company name X in the original list, the if statements will be computed:
if : If there is a match in the top 50 of both lists, then I get the name of the company with the statement "X is in the 2020 top 50 list".
elseif : If there is a match in the top 50 of the original list and the rest of the secondary list then I get the name of the company with the statement "X is in the 2020 overall list"
else : If there is no match, I get the name of the company that did not match with the statement "X is not in the 2020 list"
As of now my output is all the companies that are matches but with statement in (3) i.e. my else statement. Not sure why, but my else statement is capturing my if and elseif statement output.
Code:
year1 = data(1:end, 1:4); %tables
year30 = data(1:end, 121:124);
names30_50 = year30{1:50, 2}; %cells
names30_all = year30{:, 2};
names1_50 = year1{1:50, 2};
names1_all = year1{:, 2};
for i = 1:height(names1_50)
if contains(names30_50, names1_50{i}) %comparing both top 50 lists
disp(names1_50{i})
fprintf('%s is in the 2020 top 50 list.\n',names1_50{i})
elseif contains(names30_all, names1_50{i}) %comparing top 50 of 1990 with all of 2020
disp(names1_50{i})
fprintf('%s is in the 2020 overall list.\n',names1_50{i})
else
fprintf('%s is not in the 2020 list.\n',names1_50{i});
end
end
Output example:
General Motors is not in the 2020 list.
Ford Motor is not in the 2020 list.
Exxon Mobil is not in the 2020 list.
Intl. Business Machines is not in the 2020 list.
General Electric is not in the 2020 list.
Mobil is not in the 2020 list.
Altria Group is not in the 2020 list.
Chrysler is not in the 2020 list.
It goes on, but all of these companies are in both lists.

The contains() function is used to evaluate if a pattern is present in a string or char.
Example
you have a char ch='my_char';
%You have a char
ch = 'my_char';
%and another piece of char, the pattern
pattern = 'char';
%Evaluate if pattern is in my_char
disp(contains(ch, pattern))
% It returns true
(sorry I do not know how to include matlab code)
Here your 1st argument is a cell if I get it right. In this case the contains function returns a logical array. For each element of your cell names30_50, you know if it contains the names1_50{i} char.
But, if an if-statement is given a logical array, it will execute the bloc only if ALL element in the array are true. In your case it will obviously never happen.
What you need to do is to write
if any(contains(names30_50, names1_50{i}))
...
The any() function returns true if at least one element in the logical array is true.
By the way I would rather use the strcmp() function instead of contains().
I hope I understood correctly your problem.

Related

Checking whether values are Upper case or lower case

I'm trying to build a function in q/kdb+ that can detect whether the string passed to the function is Upper case (True) OR lower case (false)
I have done several attempts but I'm constantly hitting a road block
Here's my function, would appreciate the help. TIA
isAllCaps: {[input] if[input = lower; show 0b; show 1b]}
The above function basically takes an input as specified. It then checks from the if statement whether it is lower, if it is lower then it should return a false(0b), if not then return a true (1b). Really struggling with something so simple here. I'm just getting the following error:
evaluation error:
type
[1] isAllCaps:{[input] if[input = lower; show 0b; show 1b]}
^
[0] isAllCaps"a"
I have also tried other methods but only certain inputs were coming out to be successful.
For instance:
isAllCaps: {[x] if[ x = upper type 10h; show 1b; show 0b]}
This equates to if x is upper type string, show true, else show false. Again, getting a type error. Idk why? All the tests are in strings i.e., "John_Citizen" etc. etc.
EDIT
Tried this but I'm getting 2 outputs.
isAllCaps: {[L] if[L = lower L; show 0b; show 1b] } Am I missing something?
Try following code:
isAllCaps: {[L] show L~upper L};
It shows 1b if string is uppercase, and 0b otherwise.
There are 2 mistakes in you code
~ should be used to compare strings. = does character-wise comparison. I.e. "aa"~"aa" gives 1b, but "aa"="aa" gives 11b
Use if-else, instead of if. See 10.1.1 Basic Conditional Evaluation for more details
You can use the in-built uppercase alphabet .Q.A to achieve what you want:
{all x in .Q.A}
This lambda will return 1b if the input string consists only of capital letters and false otherwise.
Start by removing some misapprehensions.
lower returns the lower case of its argument.
show displays and returns its result. You can use it as you have to ensure the function’s result is printed on the console, but it is not required as, for example return would be in JavaScript.
If you have a boolean as the result of a test, that can just be your result.
Compare strings for equality using Match ~ rather than Equals
That said, two strategies: test for lower-case chars .Q.a, or convert to upper case and see if there is a difference.
q){not any x in .Q.a}"AAA_123"
1b
q){not any x in .Q.a}"AaA_123"
0b
The second strategy could hardly be simpler to write:
q){x~upper x}"AaA_123"
0b
q){x~upper x}"AAA_123"
1b
Together with the Apply . operator, the Zen monks construction gives you fast ‘point-free’ code – no need for a lambda:
q).[~] 1 upper\"AaA_123"
0b
q).[~] 1 upper\"AAA_123"
1b

systemverilog unpacked array concatenation

I'm trying to create an unpacked array like this:
logic [3:0] AAA[0:9];
I'd like to initialize this array to the following values:
AAA = '{1, 1, 1, 1, 2, 2, 2, 3, 3, 4};
For efficiency I'd like to use repetition constructs, but that's when things are falling apart.
Is this not possible, or am I not writing this correctly? Any help is appreciated.
AAA = { '{4{1}}, '{3{2}}, '{2{3}}, 4 };
Firstly, the construct you are using is actually called the replication operator. This might help you in future searches, for example in the SystemVerilog LRM.
Secondly, you are using an array concatenation and not an array assignment in your last block of code (note the missing apostrophe '). The LRM gives the following (simple) example in Section 10.10.1 (Unpacked array concatenations compared with array assignment patterns) to explain the difference:
int A3[1:3];
A3 = {1, 2, 3}; // unpacked array concatenation
A3 = '{1, 2, 3}; // array assignment pattern
The LRM says in the same section that
...unpacked array concatenations forbid replication, defaulting, and
explicit typing, but they offer the additional flexibility of
composing an array value from an arbitrary mix of elements and arrays.
int A9[1:9];
A9 = {9{1}}; // illegal, no replication in unpacked array concatenation
Lets also have a look at the alternative: array assignment. In the same section, the LRM mentions that
...items in an assignment pattern can be replicated using syntax, such as '{ n{element} }, and can be defaulted using the default: syntax. However, every element item in an array assignment pattern must be of the same type as the element type of the target array.
If transforming it to an array assignment (by adding an apostrophe), your code actually translates to:
AAA = '{'{1,1,1,1}, '{2,2,2}, '{3,3}, 4};
This means that the SystemVerilog interpreter will only see 4 elements and it will complain that too few elements were given in the assignment.
In Section 10.9.1 (Array assignment patterns), the LRM says the following about this:
Concatenation braces are used to construct and deconstruct simple bit vectors. A similar syntax is used to support the construction and deconstruction of arrays. The expressions shall match element for element, and the braces shall match the array dimensions. Each expression item shall be evaluated in the context of an assignment to the type of the corresponding element in the array.
[...]
A syntax resembling replications (see 11.4.12.1) can be used in array assignment patterns as well. Each replication shall represent an entire single dimension.
To help interprete the bold text in the quote above, the LRM gives the following example:
int n[1:2][1:3] = '{2{'{3{y}}}}; // same as '{'{y,y,y},'{y,y,y}}
You can't do arbitrary replication of unpacked array elements.
If your code doesn't need to be synthesized, you can do
module top;
typedef logic [3:0] DAt[];
logic [3:0] AAA[0:9];
initial begin
AAA = {DAt'{4{1}}, DAt'{3{2}}, DAt'{2{3}}, 4};
$display("%p",AAA);
end
endmodule
I had another solution but I'm not sure if it is synthesizable. Would a streaming operator work here? I'm essentially taking a packed array literal and streaming it into the data structure AAA. I've put it on EDA Playground
module tb;
logic [3:0] AAA[0:9];
initial begin
AAA = { >> int {
{4{4'(1)}},
{3{4'(2)}},
{2{4'(3)}},
4'(4)
} };
$display("%p",AAA);
end
endmodule
Output:
Compiler version P-2019.06-1; Runtime version P-2019.06-1; Mar 25 11:20 2020
'{'h1, 'h1, 'h1, 'h1, 'h2, 'h2, 'h2, 'h3, 'h3, 'h4}
V C S S i m u l a t i o n R e p o r t
Time: 0 ns
CPU Time: 0.580 seconds; Data structure size: 0.0Mb
Wed Mar 25 11:20:07 2020
Done

How can I convert this select statement to functional form?

I am having a couple of issues to put this in a functional format.
select from tableName where i=fby[(last;i);([]column_one;column_two)]
This is what I got:
?[tableName;fby;enlist(=;`i;(enlist;last;`i);(+:;(!;enlist`column_one`column_two;(enlist;`column_one;`column_two))));0b;()]
but I get a type error.
Any suggestions?
Consider using the following function, adjust from the buildQuery function given in the whitepaper on Parse Trees. This is a pretty useful tool for quickly developing in q, this version is an improvement on that given in the linked whitepaper, having been extended to handle updates by reference (i.e., update x:3 from `tab)
\c 30 200
tidy:{ssr/[;("\"~~";"~~\"");("";"")] $[","=first x;1_x;x]};
strBrk:{y,(";" sv x),z};
//replace k representation with equivalent q keyword
kreplace:{[x] $[`=qval:.q?x;x;"~~",string[qval],"~~"]};
funcK:{$[0=t:type x;.z.s each x;t<100h;x;kreplace x]};
//replace eg ,`FD`ABC`DEF with "enlist`FD`ABC`DEF"
ereplace:{"~~enlist",(.Q.s1 first x),"~~"};
ereptest:{((0=type x) & (1=count x) & (11=type first x)) | ((11=type x)&(1=count x))};
funcEn:{$[ereptest x;ereplace x;0=type x;.z.s each x;x]};
basic:{tidy .Q.s1 funcK funcEn x};
addbraks:{"(",x,")"};
//where clause needs to be a list of where clauses, so if only one whereclause need to enlist.
stringify:{$[(0=type x) & 1=count x;"enlist ";""],basic x};
//if a dictionary apply to both, keys and values
ab:{$[(0=count x) | -1=type x;.Q.s1 x;99=type x;(addbraks stringify key x),"!",stringify value x;stringify x]};
inner:{[x]
idxs:2 3 4 5 6 inter ainds:til count x;
x:#[x;idxs;'[ab;eval]];
if[6 in idxs;x[6]:ssr/[;("hopen";"hclose");("iasc";"idesc")] x[6]];
//for select statements within select statements
//This line has been adjusted
x[1]:$[-11=type x 1;x 1;$[11h=type x 1;[idxs,:1;"`",string first x 1];[idxs,:1;.z.s x 1]]];
x:#[x;ainds except idxs;string];
x[0],strBrk[1_x;"[";"]"]
};
buildSelect:{[x]
inner parse x
};
We can use this to create the functional query that will work
q)n:1000
q)tab:([]sym:n?`3;col1:n?100.0;col2:n?10.0)
q)buildSelect "select from tab where i=fby[(last;i);([]col1;col2)]"
"?[tab;enlist (=;`i;(fby;(enlist;last;`i);(flip;(lsq;enlist`col1`col2;(enlist;`col1;`col2)))));0b;()]"
So we have the following as the functional form
?[tab;enlist (=;`i;(fby;(enlist;last;`i);(flip;(lsq;enlist`col1`col2;(enlist;`col1;`col2)))));0b;()]
// Applying this
q)?[tab;enlist (=;`i;(fby;(enlist;last;`i);(flip;(lsq;enlist`col1`col2;(enlist;`col1;`col2)))));0b;()]
sym col1 col2
----------------------
bah 18.70281 3.927524
jjb 35.95293 5.170911
ihm 48.09078 5.159796
...
Glad you were able to fix your problem with converting your query to functional form.
Generally it is the case that when you use parse with a fby in your statement, q will convert this function into its k definition. Usually you should just be able to replace this k code with the q function itself (i.e. change (k){stuff} to fby) and this should run properly when turning the query into functional form.
Additionally, if you check out https://code.kx.com/v2/wp/parse-trees/ it goes into more detail about parse trees and functional form. Additionally, it contains a script called buildQuery which will return the functional form of the query of interest as a string which can be quite handy and save time when a functional form is complex.
I actually got it myself ->
?[tableName;((=;`i;(fby;(enlist;last;`i);(+:;(!;enlist`column_one`column_two;(enlist;`column_one;`column_two)))));(in;`venue;enlist`venueone`venuetwo));0b;()]
The issues was a () missing from the statement. Works fine now.
**if someone wants to add a more detailed explanation on how manual parse trees are built and how the generic (k){} function can be replaced with the actual function in q feel free to add your answer and I'll accept and upvote it

Fetch multiple securities from Yahoo using Matlab

I an trying to fetch multiple securities from Yahoo using Matlab. Since Yahoo does not support multiple fetch, so loops is used as following code:
ticker = { 'AAPL' 'MSFT' 'XOM' 'GE' 'JNJ' 'BRK.B' 'WFC' 'AMZN' 'JPM' 'FB' };
c=yahoo;
for i=1:10
Price.(ticker(i)) = fetch(c,ticker(i), 'Adj Close', 'Jan 1 05', 'Dec 31 07', 'm');
temp = Price.(ticker(i));
ClosePrice(:, i) =temp(:,2);
end
close(c);
But Matlab gives error message "Argument to dynamic structure reference must evaluate to a valid field name."
Does anyone have any insight to fix this? Thanks in advance
You're using dynamical referencing in a structure on this line:
Price.(ticker(i)) = ...
On each loop, the part in parentheses should evaluate to a string so that you effectively get Price.AAPL on the first iteration, Price.MSFT on the second, Price.XOM on the third, and so on. However, ticker is a cell array so you have to be careful using () vs {}. Using () gives you a subset of a cell array, effectively another cell array. On the other hand, using {} returns you the actual content of the cell array. To fix your code, replace any instances of (ticker(i)) with (ticker{i}).

Normalize length of cell array

I have a cell array of length 3 and I want to make a for loop with another cell array with length of 6 , so how can I add extra 3 cells for the first array in order to make the 2 cell arrays equal and to use my for loop in MATLAB?
For example, with 2 inputs:
type = { '12' '62' '5' };
colour = {'re' 'green' 'yellow' 'brown' 'blue' 'black'};
for i = 1:length(colour)
if isequal(colour(i), type(:))
result(i) = type(i);
else
end
end
I need to make the type cell array with the same size with colour cell array (I think I have to add extra 3 empty cells in side the type cell array).
I have to address several issues in your code first:
If you use a cell array, you must use curly braces ({}) to extract elements from it. Instead of writing colour(i) you should be writing colour{i}.
This is not a problem, but it's a matter of good practice. If you don't need to handle the else part of the if statement, don't write it at all.
Preallocate memory so that arrays don't grow inside the loop (it slows down the program). Specifically, add the line result = cell(size(colour)); before the for loop.
Your isequal logic is flawed. Practically, it would always return false because colour{1} is one element and type{:} is many.
According to your example, types contain numbers and colours letters, although they are both strings. Does it make sense to compare the two?
Now, regarding your question, it's up to you to decide how the for loop runs. Since you don't mention what you want to achieve (you rather ask how you want to achieve something without saying what exactly), I cannot say what your for loop should look like, if necessary at all. Maybe you meant to use ismember instead of isequal? If so, the fixed code can look like this:
result = cell(size(colour));
for i = 1:length(colour)
if ismember(colour{i}, type)
result{i} = type{i};
end
end
or shorter, like this:
result = cell(size(colour));
[found, idx] = ismember(colour, type);
result(found) = type{idx(found)}
If you provide more details, maybe I can refine my answer so that it helps you more.