In my array of strings, I have some values like "8.1076e-05". The problem I encountered while shorting. I used the code FinalHierarchy = sortrows(B, 3, 'descend'); to short, the result is below.
"FC624 " "0.010686" "9.5329e-05"
"FC642 " "0.0044959" "8.2636e-05"
"FC621 " "0.0090886" "8.1076e-05"
"FC622 " "0.0086253" "7.6943e-05"
"FC623 " "0.0080882" "7.2152e-05"
"FC643 " "0.0028437" "5.2267e-05"
"FC646 " "0.0025469" "4.6813e-05"
"FC644 " "0.0012072" "2.2189e-05"
"FC122 " "0.0073847" "0.00077775"
"FC142 " "0.010012" "0.00072479"
"FC131 " "0.0094101" "0.00071951"
"FC121 " "0.0068294" "0.00071926"
"FC521 " "0.0095355" "0.00069401"
"FC112 " "0.0087711" "0.00063404"
"FC111 " "0.008607" "0.00062218"
"FC531 " "0.0058125" "0.00055105"
"FC141 " "0.0074634" "0.0005403"
"FC228 " "0.0098074" "0.00049734"
"FC224" "0.009434" "0.0004784"
"FC221 " "0.0092251" "0.00046782"
"FC225" "0.0088874" "0.00045069"
It can be seen above that MATLAB has considered the value 2.2189e-05 bigger than 0.00077775. I guess the reason behind it is, MATLAB compared 2.2189 with 0.00077775. It is because the column is a string. In my calculation, column 2 and column 3 were double but when I concatenated them with a string column 1 as 'B', it became string.
I guess it might have a very easy solution if 2.2189e-05 stays as 0.00002219. I try to change the format to longG but the problem still persists.
Can someone suggest any idea to deal with it?
As you said, it is because your elements are strings. So what you could do is:
% Sort the column after having casted it to double
[~, idx] = sort(str2double(B(:, 3)), 'descend');
% Apply the sorting to the initial matrix
FinalHierarchy = B(idx, :);
Related
I have the below code in MATLAB. I use version R2019a.
clc;
clear all;
K = 100;
r = 5:1:55;
W = 10;
t = round((2*K.*r.^2+W^2)./60);
%disp("Turn : " + r + " " + t);
str = "Turn : ";
fprintf("%s %d %d",str,r,t)
I want to use fprintf instead of disp. r and t are 1x51 double variables.
When I use fprintf without %s and str, the script prints 51 values one by one without a roblem. But if I use %s and str in fprintf it only prints the first line "Turn : 5 6 ", then it prints out strange characters as below.
If I use disp, it works correctly as below.
I was just reading this blog post by Loren Shure of the MathWorks. It taught me about compose. compose perfectly solves your problem. Use it instead of fprintf to combine your data into strings. Then use fprintf to print the strings to screen:
s = compose("%s %d %d", str, r.', t.');
fprintf("%s\n", s)
compose is much more intuitive than fprintf in how the values for each % element is taken from the input data. It generates one string for each row in the data. str is a scalar, its value will be repeated for each row. r.' and t.' here have the same number of rows, which will also be the number of rows in s.
Note: compose is new in MATLAB R2016b.
You don't actually need any functions. When working with strings, if you use the + operator you get the conversion for free:
>> str + r + " " + t
ans =
1×51 string array
Columns 1 through 5
"Turn : 5 85" "Turn : 6 122" "Turn : 7 165" "Turn : 8 215" "Turn : 9 272"
...
I have a super simple formula. The problem is that sometimes the data doesn't have a second value, or sometimes the value is blank.
Split ({PO_RECEIVE.VENDOR_LOT_ID}," ")[2]
ID
111 222
123
123 222
I was thinking if I could come up with some logic to figure out whether the string has multiple value's it would solve my problem, but haven't quiet found what I'm looking for:
If {PO_RECEIVE.VENDOR_LOT_ID} = SingleOrBlankString then
{PO_RECEIVE.VENDOR_LOT_ID} else
Split ({PO_RECEIVE.VENDOR_LOT_ID}," ")[2]
Better Example Data:
3011111*42011111111
2711 00291111111
711111//12111111111
/J1111 69111111111
170111
If the string can contain a maximum of two values, separated by a space, then you can check if the string contains a space using the InStr function:
If InStr({PO_RECEIVE.VENDOR_LOT_ID}, " ") > 0 Then
{PO_RECEIVE.VENDOR_LOT_ID}
Else
Split ({PO_RECEIVE.VENDOR_LOT_ID}," ")[2]
If there can be multiple spaces between the parts you can use following formulas to get the values:
Left part:
This function returns the left part of the string until the first space.
If InStr({PO_RECEIVE.VENDOR_LOT_ID}, " ") > 0 Then
Left({PO_RECEIVE.VENDOR_LOT_ID}, InStr({PO_RECEIVE.VENDOR_LOT_ID}, " "))
Right part:
This function returns the right part of the string after the last space.
The InStrRev-function returns the position of the last space because it searches the string backwards.
The Len-function returns the length of the string.
[length] - [position of last space] = [length of the right part]
If InStr({PO_RECEIVE.VENDOR_LOT_ID}, " ") > 0 Then
Right({PO_RECEIVE.VENDOR_LOT_ID}, Len({PO_RECEIVE.VENDOR_LOT_ID}) - InStrRev(testString, " "))
I have a database field with strings like this
oh the sea OToole was right
I like ramen but
Rowing like a Blue but not an artist
They are actual words separated with space
I want to find to extract the first 3 words
The result would be like below
oh the sea
I like ramen
Rowing like a
I tried the following
ExtractString({tbname.field1},""," ") & " " & ExtractString({tbname.field1}," "," ") & ExtractString({tbname.field1}," "," ")
It did work for the the first two fields but not the second
I tried the one below too
split({tbname.field1}, " ")[1] & " " & split({tbname.field1}, " ")[2]
& " " & split({tbname.field1}, " ")[3]
It gives me an error saying the indice must be between 1 and the size of the array
Any insights are more than welcome
if ubound(Split({tbname.field1})) < 3 then
Join(Split({tbname.field1})[1 to ubound(Split({tbname.field1}))]," ")
else Join(Split({tbname.field1})[1 to 3]," ")
** edited to reflect data is contained in a single row, rather than 3 separate rows
Try:
// defined delimiter
Local Stringvar CRLF := Chr(10)+Chr(13);
// split CRLF-delimited string into an array
Local Stringvar Array rows := Split({Command.WORDS}, CRLF);
// the results of all the work
Local Stringvar Array results;
// process each 'row'
Local Numbervar i;
for i := 1 to ubound(rows) do (
// increment the array, then add first 3 words
Redim Preserve results[Ubound(results)+1];
results[ubound(results)]:=Join(Split(rows[i])[1 to 3]," ")
);
// create CRLF-delimited string
Join(results, CRLF);
I have a column of strings that look like this:
Target Host: dcmxxxxxxc032.erc.nam.fm.com Target Name:
dxxxxxxgsc047.erc.nam.fm.com Filesystem /u01 has 4.98% available space
- fallen below warning (20) or critical (5) threshold.
The column name is [Description]
The substring I would like returned is (dxxxxxxgsc047.erc.nam.fm.com)
The only consistency in this data is that the desired string occurs between the 5th and 6th occurrences of spaces " " in the string, and after the phrase "Target Name: " The length of the substring varies, but it always ends in another " ", hence my attempt to grab the substring between the 5th and 6th spaces.
I have tried
MID([Description],((FIND([Description],"Target Name: "))+13),FIND([Description]," ",((FIND([Description],"Target Name"))+14)))
But that does not work.
(Edit: We use Tableau 8.2, the Tableau 9 only functions can't be part of the solution, thanks though!)
Thank you in advance for your help.
In Tableau 9 you can use regular expressions in formulas, it makes the task simpler:
REGEXP_EXTRACT([Description], "Target Name: (.*?) ")
Alternatively in Tableau 9 you can use the new FINDNTH function:
MID(
[Description],
FINDNTH([Description]," ", 5) + 1,
FINDNTH([Description]," ", 6) - FINDNTH([Description]," ", 5) - 1
)
Prior to Tableau 9 you'd have to use string manipulation methods similar to what you've tried, just need to be very careful with arithmetic and providing the right arguments (the third argument in MID is length, not index of the end character, so we need to subtract the index of the start character):
MID(
[Description]
, FIND([Description], "Target Name:") + 13
, FIND([Description], " ", FIND([Description], "Target Name:") + 15)
- (FIND([Description], "Target Name:") + 13)
)
Well, you need to find "Target name: " and then the " " after it, not so hard. I'll split in 3 fields just to be more clear (you can mix everything in a single field). BTW, you were in the right direction, but the last field on MID() should be the string length, not the char position
[start]:
FIND([Description],"Target name: ")+13
[end]:
FIND([Description]," ",[start])
And finally what you need:
MID([Description],[start]+1,[end]-[start]-1)
This should do. If you want to pursue the 5th and 6th " " approach, I would recommend you to find each of the " " until the 6th.
[1st]:
FIND([Description], " ")
[2nd]:
FIND([Description], " ",[1st] + 1)
And so on. Then:
MID([Description],[5th]+1,[6th]-[5th]-1)
A simple solution -
SPLIT( [Description], " ", 3 )
This returns a substring from the Description string, using the space delimiter character to divide the string into a sequence of tokens.
The string is interpreted as an alternating sequence of delimiters and
tokens. So for the string abc-defgh-i-jkl, where the delimiter
character is ‘-‘, the tokens are abc, defgh, i and jlk. Think of these
as tokens 1 through 4. SPLIT returns the token corresponding to the
token number. When the token number is positive, tokens are counted
starting from the left end of the string; when the token number is
negative, tokens are counted starting from the right. -
Tableau String Functions
I don't know Tableau, but perhaps something like this?
MID(
MID([Description], FIND([Description],"Target Name: ") + 13, 50),
1,
FIND(MID([Description], FIND([Description],"Target Name: ") + 13, 50), " ")
)
I have a text field that has the following expression:
$F{casNo} + " Total " + $P{chosenUom} + ": " + $V{total_COUNT}
casNo is a string, chosenUom is a string. total_COUNT is a sum variable of doubles. The total_COUNT variable displays, but it's got 8 - 10 decimal places (1.34324255234), all I need is something along the lines of 1.34.
Here's what I tried already:
$F{casNo} + " Total " + $P{chosenUom} + ": " + new DecimalFormat("0.00").format($V{total_COUNT}).toString()
Any help would be appreciated
For now I'm just doing basic math, but I'm hoping for a real solution, not a workaround
((int)($V{total_COUNT}*100.0))/100.0
You can format the in lline numbers by using:
new DecimalFormat("###0.00").format(YOUR NUMBER)
You might split the text field into two, one containing everything but the $V{total_COUNT}, and the second containing only $V{total_COUNT}, but with the Pattern property set to something like "#0.00".
You'd have to get a bit creative with layout, though, to prevent unwanted word-wrapping and spacing; for example, first text field could be wide and right-aligned, while text field containing the count could be left-aligned and wide enough to accommodate the formatted number.