I have a cell array. Some of the elements in this cell array contains zeros as the first character and the whole element is only numbers (double) as well. When exporting these to Excel (which I prefer), the zeros are deleted and converting it to a number.
Let's take an example to illustrate my problem. I have a cell array with 10 elements:
NodeID = {'0000006';
'0000011';
'000011R';
'000016R';
'000021R';
'B276_2';
'EB 7.55';
'EB2521';
'EllebaekOPlB1';
'EllebaekOplB10'};
The first two elements contains zeros until the number 6 and 11, respectively. Unlike the third element and so forth, where letters are involved. So when exporting NodeID to Excel, it returns this in a column (I use writetable command by the way):
6
11
000011R
000016R
000021R
B276_2
EB 7.55'
EB2521
EllebaekOPlB1
EllebaekOplB10
Notice the removal of zeros for the first two elements. Now I know that in Excel, it will keep all the content with the addition of a quote symbol ' in front of the cell, eg. '0000006 for the first element.
I have searched in many places to find a solution to this. But is there a good way to avoid this from happening? Either by somehow adding an extra ยด or some other magical trick which I have not seen?
Thank you in advance!
One alternative (if your values are in a cell, as you say they are):
filename = 'NodeID.xlsx';
NodeID2 = cellfun(#(C) ['''',C], NodeID,'UniformOutput', false)
xlswrite(filename, NodeID2)
This gives you:
NodeID2 =
''0000006'
''0000011'
''000011R'
''000016R'
''000021R'
''B276_2'
''EB 7.55'
''EB2521'
''EllebaekOPlB1'
''EllebaekOplB10'
And an Excel file looking like this:
The cellfun line is equivalent to:
for ii = 1:numel(NodeID)
NodeID2{ii,1} = ['''', NodeID{ii}];
end
The part ['''', NodeID{ii}] inserts a single quotation mark in front for the string. Relevant answer.
I have a query which I am trying to solve
I know that one can use strcmp(s1,s2) to compare two different strings to see whether they are the same. It gives 1 if that is the case.
However, how would one tackle this problem if you have a variable length array full of strings and you want to the whether all strings in the array are the same.
For example: ['NACA64A010' 'NACA64A010' 'NACA64A010' 'NACA64A010'] we can see that all the strings are the same in this array. However, how would one go about with using strcmp(s1,s2).
Thanks guys!
If you want all pairwise comparisons between strings: call ndgrid to generate indices of all combinations, and then index into your cell array of strings and call strcmp:
x = {'NACA64A010' 'NACA64A010' 'NACA64A010' 'NACA64A010'};
[ii, jj] = ndgrid(1:numel(x));
result = strcmp(x(ii), x(jj));
In this case
result =
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
because all strings are the same.
You probably had a pairwise comparison using strcmp in mind, but you can use it directly on cell arrays:
x={'NACA64A010' 'NACA64A010' 'NACA64A010' 'NACA64A010'}
result=all(strcmpi(x{1},x(2:end)))
Compare the first element to the remaining elements. It returns true only if all elements are equal. For a pairwise comparison you could us:
[~,~,c]=unique(x);
result=bsxfun(#eq,c,c.')
If you're solving the problem with a matrix (i.e. every row is a string) there are no particularly nice solutions in my opinion, but if your strings are contained into a cell array, things are getting easier and nicer.
So we start by creating such cell array:
myStrings={'NACA64A010' 'NACA64A010' 'NACA64A010' 'NACA64A010'};
where each cell contains a string. This will make your code more robust as well since every string can have a different length (this is not true if you concatenate all your strings in a matrix).
Then you specify which string you want to find inside such cell array:
stringThatMustBeTested='NACA64A010';
Now you can use cellfun(), which is a function that applies another function to every cell of a given cell array as follows:
results=cellfun(#(x) strcmp(x,stringThatMustBeTested),myStrings);
Such line simply means "apply strcmp() to every generic cell x inside myStrings and compare the cell with stringThatMustBeTested".
Variable results will be a logical output in which element j will be true if the j-th cell in your cell array is equal to the string you want to test. If results is entirely composed by 1s (which you can check as if sum(results)==length(results)), then all the strings are the same in myStrings (given that stringThatMustBeTested is the unique string in your cell array but anyways, this solution can be extended to a broader string search inside a cell).
I have a string array:
size(entries)
ans =
1 19413
I would like to rearrange the array to 4853 rows and 4 columns:
output=permute(entries,[4853 4]);
but get following error:
Error using permute ORDER contains an invalid permutation index.
What is the (probably obvious thing) I am doing wrong? thanks
You currently have 19413 elements, yet you wish to reshape this into a 4853 x 4 matrix that consists of 4853 * 4 = 19412 elements. No function in the world will help you do this because the original and target amount of elements don't match - they're off by one element. If you remove one of the elements...say... the last one, then we're getting somewhere.
Supposing you made a mistake and included that extra element by accident, you don't use permute here, but you use reshape. The second argument to reshape is the amount of elements to spread out for each target dimension, and that's what you're looking for. First remove the extraneous element that appears at the end of the array, then reshape the matrix:
output = reshape(entries(1:end-1),[4853 4]);
I'm 3 years late, but here's to anyone still looking for an answer.
In your case as mentioned above, yes you should use reshape() while minding that you preserve the total number of elements.
You use permute() when you want to reorder the dimensionality of an n-dimensional (ND) matrix.
The ORDER parameter specifies the order of the columns.
For example, if matrix A is LxMxN, the following line would make it MxLxN.
A = permute(A,[2 1 3]);
Hope this clears things.
In Microsoft Excel I have three arrays. When I match values in array 1 and array 2, I want to copy the cell in array 3 (that is in the same row as the match in array 2) to a new cell.
I'd recommend creating a 3rd hidden column that is a concatenation of array1 and array2 to the left of array3. Then you can concatenate your input in the formula and do a simple VLOOKUP.
=iferror( vlookup( concatinate( <input1>, <input2>), <table>, 2, False), <err condition>)
Checking if a value is in an array can be done with ISNUMBER(MATCH()).
The result above
Can be achieved with =IF(ISNUMBER(MATCH(B1,$A$1:$A$8,0)),C1,"") which checks whether it's anywhere in the array and prints column three if it is.
Assuming arrays 1, 2 & 3 (including headers) are located atB6:B27, C6:C27 & D6:D27 (adjust as required)
At least 3 formulas will return the required results:
Formula 1 : Enter this formula in F7 then copy till last record:
=IF(ISNA(VLOOKUP($C7,$B$7:$B$27,1,0)),"",$D7)
Formula 2 : Enter this formula in G7 then copy till last record:
=IF(ISNA(MATCH($C7,$B$7:$B$27,0)),"",$D7)
Formula 3 : Enter this Formula in H7 then copy till last record:
=IF(ISNA(MATCH($C$7:$C$27,$B$7:$B$27,0)),"",$D$7:$D$27)
I can't seem to get this down, right.
I have a big list of words in an array. I want these words to appear in 8 'tables', each 14 rows by 9 columns, with words running down each column of the table.
So I can get as far as columns = words.each_slice(14) and then later tables = columns.each_slice(9) but from there i'm not sure. I feel like I should make a hash and append the first n item of each column to an array, and then maybe join them with a tab delimiter.
My destination is a spreadsheet, so maybe outputting to CSV would make sense? I'm just not sure how to have it grouped into separate 'tables' (instead of just 9 columns with lots of rows and no separation) but maybe all it takes is a csv line with all blanks?
Anyway, any input or insight would be welcome.
This will do what you ask
You don't say anything about the output format you want, so I've just surrounded each word with quotes, joined them with commas and put a blank line between tables.
My "words" are just the numbers 1 to 200.
words = (1 .. 200).map { |v| '%03d' % v }
words.each_slice(14).each_slice(9) do |table|
(0 ... table[0].size).each do |i|
row = table.map { |column| column[i] }
row.pop if row[-1].nil?
puts row.map { |cell| %<"#{cell}"> }.join ','
end
puts ''
end
output
"001","015","029","043","057","071","085","099","113"
"002","016","030","044","058","072","086","100","114"
"003","017","031","045","059","073","087","101","115"
"004","018","032","046","060","074","088","102","116"
"005","019","033","047","061","075","089","103","117"
"006","020","034","048","062","076","090","104","118"
"007","021","035","049","063","077","091","105","119"
"008","022","036","050","064","078","092","106","120"
"009","023","037","051","065","079","093","107","121"
"010","024","038","052","066","080","094","108","122"
"011","025","039","053","067","081","095","109","123"
"012","026","040","054","068","082","096","110","124"
"013","027","041","055","069","083","097","111","125"
"014","028","042","056","070","084","098","112","126"
"127","141","155","169","183","197"
"128","142","156","170","184","198"
"129","143","157","171","185","199"
"130","144","158","172","186","200"
"131","145","159","173","187"
"132","146","160","174","188"
"133","147","161","175","189"
"134","148","162","176","190"
"135","149","163","177","191"
"136","150","164","178","192"
"137","151","165","179","193"
"138","152","166","180","194"
"139","153","167","181","195"
"140","154","168","182","196"
You were on the right track. Here's a solution that writes in CSV format for lists whose length is a multiple of 14*9. You can also create a spreadsheet directly with the appropriate gem. I'll post an update which handles any length list shortly.
Note that I think each_slice requires you to include Enumerable for at least pre 2.0 Ruby versions.
(0...14*9*2).each_slice(14).collect.each_slice(9) {|table|
table.transpose.each {|row|
puts row.inspect.delete('[]')} ; puts}
If you need to pad your input array to a multiple of 14*9 so that the transpose works, you can use the following:
def print_csv(array)
mod=array.length%(14*9)
array = array+[nil]*(14*9-mod) if mod>0
array.each_slice(14).collect.each_slice(9) {|table|
table.transpose.each {|row|
puts row.reject(&:nil?)*','} ; puts}
end