MATLAB - Only First Letter of String is Printing - string

I am having an issue printing a string in MATLAB (2012a) using the fprtinf command (and sprintf).
I have an array of 12 dates (numeric). I am converting them to strings using the following command:
months = datestr(data(:,1)-365,12); %Mar13 format
I obtain the following (and desired) output when I call the months variable:
Jan12
Feb12
Mar12
Apr12
etc..
The issue is when I call the fprintf or sprintf, say with the following code:
fprintf('%s', months(1))
I will only get the first letter of the month and not the full string. Any idea how to make it print the full string?
Thanks!

The resulting data type for your months variable is an NxM character array. You need to process it as a cell array of strings instead.
dates = num2cell(data(:,1)-365)
months = cellfun(#(x) datestr(x,12),dates,'UniformOutput',false)
fprintf('%s', months{1})
should get you what you want.

Simply change your call to
fprintf('%s', months(1, :))
datestr returns the string of each of the supplied dates on a separate row.
Alternatively you could use the cellstr function to convert the result to a cell array (this would also work with non fixed-length date formats like 'dddd')
months = cellstr(months);
fprintf('%s', months{1});

Related

Extract number as an an integer from a string

I have some data which is badly formatted ( inherited) after some manipulation and some concatenation I have something resembling the following in a string
"SIGNAGE -- 11 Requires door signage. "
My table has to cross reference a some data from a VLOOKUP and then tries to get the first chars in a pattern after the --
My formula is this
=IF(VLOOKUP($C3,DoorCheck!$D3:$AD79,19,FALSE)<>"",LEFT((RIGHT((VLOOKUP($C3,DoorCheck!$D3:$AD79,19,FALSE)), LEN((VLOOKUP($C3,DoorCheck!$D3:$AD79,19,FALSE)))-SEARCH("--", (VLOOKUP($C3,DoorCheck!$D3:$AD79,19,FALSE)),1)-2)),2),"")
This successfully gives me the number 11.
My problem is that the number is being treated as a string and not as a numeric value.
What am I missing?
Use NUMBERVALUE() function to convert a string into a number.
I often use the trick when getting numbers out of text with LEFT(), MID() or RIGHT() to do a "*1" as the final step.
=mid(....) *1
for example,
So, yours would be :
=IF(VLOOKUP($C3,DoorCheck!$D3:$AD79,19,FALSE)<>"",LEFT((RIGHT((VLOOKUP($C3,DoorCheck!$D3:$AD79,19,FALSE)), LEN((VLOOKUP($C3,DoorCheck!$D3:$AD79,19,FALSE)))-SEARCH("--", (VLOOKUP($C3,DoorCheck!$D3:$AD79,19,FALSE)),1)-2)),2),"")*1

Convert date into numeric date

In Matlab, how can I convert a date into a numeric date?
For example, I want to convert '31-Jan-1990' to '19900131'.
You can use datestr to change the date format to 19900131, and then use str2double to convert it to a number:
numDate = str2double(datestr('31-Jan-1990','yyyymmdd'))
numDate =
19900131
If you want to keep the date as a string just remove str2double from the above code.
Here are two functions that are the most helpful and appropriate ones for this situation:
datenum and datestr
The first step is to convert your string to Matlab's date number, which can be later converted to any string format, or even do calculation for date or time. Here we use additional argument to help on conversion. You may also check here for format you like to construct.
daynum = datenum('31-Jan-1990','dd-mm-YYYY')
The second step is then straightforward. You use the date number to translate to the string with the format you want.
datestr(daynum,'YYYYmmdd');
You can sure combine both functions together
datestr(datenum('31-Jan-1990','dd-mm-YYYY'),'YYYYmmdd')
The result
>> datestr(datenum('31-Jan-1990','dd-mm-YYYY'),'YYYYmmdd')
ans =
'19900131'
Finally, use str2num to achieve what you want.

Remove text from excel cell before first occurance of special character [duplicate]

Is there an efficient way to identify the last character/string match in a string using base functions? I.e. not the last character/string of the string, but the position of a character/string's last occurrence in a string. Search and find both work left-to-right so I can't think how to apply without lengthy recursive algorithm. And this solution now seems obsolete.
I think I get what you mean. Let's say for example you want the right-most \ in the following string (which is stored in cell A1):
Drive:\Folder\SubFolder\Filename.ext
To get the position of the last \, you would use this formula:
=FIND("#",SUBSTITUTE(A1,"\","#",(LEN(A1)-LEN(SUBSTITUTE(A1,"\","")))/LEN("\")))
That tells us the right-most \ is at character 24. It does this by looking for "#" and substituting the very last "\" with an "#". It determines the last one by using
(len(string)-len(substitute(string, substring, "")))\len(substring)
In this scenario, the substring is simply "\" which has a length of 1, so you could leave off the division at the end and just use:
=FIND("#",SUBSTITUTE(A1,"\","#",LEN(A1)-LEN(SUBSTITUTE(A1,"\",""))))
Now we can use that to get the folder path:
=LEFT(A1,FIND("#",SUBSTITUTE(A1,"\","#",LEN(A1)-LEN(SUBSTITUTE(A1,"\","")))))
Here's the folder path without the trailing \
=LEFT(A1,FIND("#",SUBSTITUTE(A1,"\","#",LEN(A1)-LEN(SUBSTITUTE(A1,"\",""))))-1)
And to get just the filename:
=MID(A1,FIND("#",SUBSTITUTE(A1,"\","#",LEN(A1)-LEN(SUBSTITUTE(A1,"\",""))))+1,LEN(A1))
However, here is an alternate version of getting everything to the right of the last instance of a specific character. So using our same example, this would also return the file name:
=TRIM(RIGHT(SUBSTITUTE(A1,"\",REPT(" ",LEN(A1))),LEN(A1)))
How about creating a custom function and using that in your formula? VBA has a built-in function, InStrRev, that does exactly what you're looking for.
Put this in a new module:
Function RSearch(str As String, find As String)
RSearch = InStrRev(str, find)
End Function
And your function will look like this (assuming the original string is in B1):
=LEFT(B1,RSearch(B1,"\"))
New Answer | 31-3-2022:
With even newer functions come even shorter answers. At time of writing in BETA, but probably widely available in the near future, we can use TEXTBEFORE():
=LEN(TEXTBEFORE(A2,B2,-1))+1
The trick here is that the 3rd parameter tells the function to retrieve the last occurence of the substring we give in the 2nd parameter. At time of writing this function is still case-sensitive by default which could be handeld by the optional 4th parameter.
Original Answer | 17-6-2020:
With newer versions of excel come new functions and thus new methods. Though it's replicable in older versions (yet I have not seen it before), when one has Excel O365 one can use:
=MATCH(2,1/(MID(A1,SEQUENCE(LEN(A1)),1)="Y"))
This can also be used to retrieve the last position of (overlapping) substrings:
=MATCH(2,1/(MID(A1,SEQUENCE(LEN(A1)),2)="YY"))
| Value | Pattern | Formula | Position |
|--------|---------|------------------------------------------------|----------|
| XYYZ | Y | =MATCH(2,1/(MID(A2,SEQUENCE(LEN(A2)),1)="Y")) | 3 |
| XYYYZ | YY | =MATCH(2,1/(MID(A3,SEQUENCE(LEN(A3)),2)="YY")) | 3 |
| XYYYYZ | YY | =MATCH(2,1/(MID(A4,SEQUENCE(LEN(A4)),2)="YY")) | 4 |
Whilst this both allows us to no longer use an arbitrary replacement character and it allows overlapping patterns, the "downside" is the useage of an array.
Note: You can force the same behaviour in older Excel versions through either
=MATCH(2,1/(MID(A2,ROW(A1:INDEX(A:A,LEN(A2))),1)="Y"))
Entered through CtrlShiftEnter, or using an inline INDEX to get rid of implicit intersection:
=MATCH(2,INDEX(1/(MID(A2,ROW(A1:INDEX(A:A,LEN(A2))),1)="Y"),))
tigeravatar and Jean-François Corbett suggested to use this formula to generate the string right of the last occurrence of the "\" character
=TRIM(RIGHT(SUBSTITUTE(A1,"\",REPT(" ",LEN(A1))),LEN(A1)))
If the character used as separator is space, " ", then the formula has to be changed to:
=SUBSTITUTE(RIGHT(SUBSTITUTE(A1," ",REPT("{",LEN(A1))),LEN(A1)),"{","")
No need to mention, the "{" character can be replaced with any character that would not "normally" occur in the text to process.
Just came up with this solution, no VBA needed;
Find the last occurance of "_" in my example;
=IFERROR(FIND(CHAR(1);SUBSTITUTE(A1;"_";CHAR(1);LEN(A1)-LEN(SUBSTITUTE(A1;"_";"")));0)
Explained inside out;
SUBSTITUTE(A1;"_";"") => replace "_" by spaces
LEN( *above* ) => count the chars
LEN(A1)- *above* => indicates amount of chars replaced (= occurrences of "_")
SUBSTITUTE(A1;"_";CHAR(1); *above* ) => replace the Nth occurence of "_" by CHAR(1) (Nth = amount of chars replaced = the last one)
FIND(CHAR(1); *above* ) => Find the CHAR(1), being the last (replaced) occurance of "_" in our case
IFERROR( *above* ;"0") => in case no chars were found, return "0"
Hope this was helpful.
You could use this function I created to find the last instance of a string within a string.
Sure the accepted Excel formula works, but it's much too difficult to read and use. At some point you have to break out into smaller chunks so it's maintainable. My function below is readable, but that's irrelevant because you call it in a formula using named parameters. This makes using it simple.
Public Function FindLastCharOccurence(fromText As String, searchChar As String) As Integer
Dim lastOccur As Integer
lastOccur = -1
Dim i As Integer
i = 0
For i = Len(fromText) To 1 Step -1
If Mid(fromText, i, 1) = searchChar Then
lastOccur = i
Exit For
End If
Next i
FindLastCharOccurence = lastOccur
End Function
I use it like this:
=RIGHT(A2, LEN(A2) - FindLastCharOccurence(A2, "\"))
Considering a part of a Comment made by #SSilk my end goal has really been to get everything to the right of that last occurence an alternative approach with a very simple formula is to copy a column (say A) of strings and on the copy (say ColumnB) apply Find and Replace. For instance taking the example: Drive:\Folder\SubFolder\Filename.ext
This returns what remains (here Filename.ext) after the last instance of whatever character is chosen (here \) which is sometimes the objective anyway and facilitates finding the position of the last such character with a short formula such as:
=FIND(B1,A1)-1
I'm a little late to the party, but maybe this could help. The link in the question had a similar formula, but mine uses the IF() statement to get rid of errors.
If you're not afraid of Ctrl+Shift+Enter, you can do pretty well with an array formula.
String (in cell A1):
"one.two.three.four"
Formula:
{=MAX(IF(MID(A1,ROW($1:$99),1)=".",ROW($1:$99)))} use Ctrl+Shift+Enter
Result: 14
First,
ROW($1:$99)
returns an array of integers from 1 to 99: {1,2,3,4,...,98,99}.
Next,
MID(A1,ROW($1:$99),1)
returns an array of 1-length strings found in the target string, then returns blank strings after the length of the target string is reached: {"o","n","e",".",..."u","r","","",""...}
Next,
IF(MID(I16,ROW($1:$99),1)=".",ROW($1:$99))
compares each item in the array to the string "." and returns either the index of the character in the string or FALSE: {FALSE,FALSE,FALSE,4,FALSE,FALSE,FALSE,8,FALSE,FALSE,FALSE,FALSE,FALSE,14,FALSE,FALSE.....}
Last,
=MAX(IF(MID(I16,ROW($1:$99),1)=".",ROW($1:$99)))
returns the maximum value of the array: 14
Advantages of this formula is that it is short, relatively easy to understand, and doesn't require any unique characters.
Disadvantages are the required use of Ctrl+Shift+Enter and the limitation on string length. This can be worked around with a variation shown below, but that variation uses the OFFSET() function which is a volatile (read: slow) function.
Not sure what the speed of this formula is vs. others.
Variations:
=MAX((MID(A1,ROW(OFFSET($A$1,,,LEN(A1))),1)=".")*ROW(OFFSET($A$1,,,LEN(A1)))) works the same way, but you don't have to worry about the length of the string
=SMALL(IF(MID(A1,ROW($1:$99),1)=".",ROW($1:$99)),2) determines the 2nd occurrence of the match
=LARGE(IF(MID(A1,ROW($1:$99),1)=".",ROW($1:$99)),2) determines the 2nd-to-last occurrence of the match
=MAX(IF(MID(I16,ROW($1:$99),2)=".t",ROW($1:$99))) matches a 2-character string **Make sure you change the last argument of the MID() function to the number of characters in the string you wish to match!
In newer versions of Excel (2013 and up) flash fill might be a simple and quick solution see: Using Flash Fill in Excel
.
For a string in A1 and substring in B1, use:
=XMATCH(B1,MID(A1,SEQUENCE(LEN(A1)),LEN(B1)),,-1)
Working from inside out, MID(A1,SEQUENCE(LEN(A1)),LEN(B1)) splits string A1 into a dynamic array of substrings, each the length of B1. To find the position of the last occurrence of substring B1, we use XMATCH with its Search_mode argument set to -1.
A simple way to do that in VBA is:
YourText = "c:\excel\text.txt"
xString = Mid(YourText, 2 + Len(YourText) - InStr(StrReverse(YourText), "\" ))
Very late to the party, but A simple solution is using VBA to create a custom function.
Add the function to VBA in the WorkBook, Worksheet, or a VBA Module
Function LastSegment(S, C)
LastSegment = Right(S, Len(S) - InStrRev(S, C))
End Function
Then the cell formula
=lastsegment(B1,"/")
in a cell and the string to be searched in cell B1 will populate the cell with the text trailing the last "/" from cell B1.
No length limit, no obscure formulas.
Only downside I can think is the need for a macro-enabled workbook.
Any user VBA Function can be called this way to return a value to a cell formula, including as a parameter to a builtin Excel function.
If you are going to use the function heavily you'll want to check for the case when the character is not in the string, then string is blank, etc.
If you're only looking for the position of the last instance of character "~" then
=len(substitute(String,"~",""))+1
I'm sure there is version that will work with the last instance of a string but I have to get back to work.
Cell A1 = find/the/position/of/the last slash
simple way to do it is reverse the text and then find the first slash as normal. Now you can get the length of the full text minus this number.
Like so:
=LEN(A1)-FIND("/",REVERSETEXT(A1),1)+1
This returns 21, the position of the last /

How to print a number within a string in matlab

I would like to use the command text to type numbers within 57 hexagons. I want to use a loop:
for mm=1:57
text(x(m),y(m),'m')
end
where x(m) and y(m) are the coordinates of the text .
The script above types the string "m" and not the value of m. What am I doing wrong?
Jubobs pretty much told you how to do it. Use the num2str function. BTW, small typo in your for loop. You mean to use mm:
for mm=1:57
text(x(mm),y(mm),num2str(mm));
end
The reason why I've even decided to post an answer is because you can do this vectorized without a loop, which I'd also like to write an answer for. What you can do place each number into a character array where each row denotes a unique number, and you can use text to print out all numbers simultaneously.
m = sprintfc('%2d', 1:57);
d = reshape([m{:}], 2, 57).';
text(x, y, d);
The (undocumented!) function sprintfc takes a formatting specifier and an array and creates a cell array of strings where each cell is the string version of each element in the array you supply. In order to ensure that the character array has the same number of columns per row, I ensure that each string takes up 2 characters, and so any number less than 10 will have a blank space at the beginning. I then convert the cell array of strings into a character array by converting the cell array into a comma-separated list of strings and I reshape the matrix into an acceptable form, and then I call text with all of the pairs of x and y, with the corresponding labels in m together on the screen.

I want to extract only last two numeric values from a string variable in SAS

I want to extract only last two numeric values from a string variable and assign it to a new variable. Firstly i have extracted all the numeric values from the string using the code below and assigned it to a new variable but i ultimately want to extract only the last two numeric values so is there any better way to do this.
UI_DUM = input(compress(Prod_Desc,,"kd"),best.);
And one more question is: how to assign a temp variable for doing some manupulation work in SAS?
Here is the code.
You are doing it right, to remove the characters and keeping only digits. The same is being done for variable "temp1"(in the below code).
In the second step, using the length function, to calculate the total length of the string which now contains only digits. In the third step using the substr function to extract the last two digits.
If you want to do it in one statement, "final" variable is the answer.
LENGTH Function - Returns the length of a non-blank character string, excluding
trailing blanks, and returns 1 for a blank character string
compress function with "kd" option - would keep only digits.
COMPRESS(<, chars><, modifiers>)
Modifier - specifies a character constant, variable, or expression in which each non-blank character modifies the action of the COMPRESS function. Blanks are ignored. The following characters can be used as modifiers.
d or D adds digits to the list of characters.
k or K keeps the characters in the list instead of removing them
substr function - Extracts a substring from an argument -
SUBSTR(string, position<,length>)
data _null_;
Test_string="ada13117a1w11da1286s";
temp1=compress(Test_string, , 'kd');
temp2=length(temp1);
temp3=substr(temp1,temp2-1,2);
final=substr(compress(Test_string, , 'kd'),length(compress(temp1))-1,2);
put _all_;
run;
Regarding the temp variable, there is no such one in SAS. Just use any variable name and use the drop statement in final dataset like below;
data test(drop = temp); /*Would work as the temp variable*/
temp= 2*balance;/*just for example*/
/*use the temp in further calculations*/
run;
A somewhat different take:
data want;
set have;
UI_DUM = input(compress(Prod_Desc,,"kd"),best.);
UI_DUM_last2 = mod(UI_DUM,100);
run;
You could do that all in one line of course as well. This uses the numeric modulo function to simply give you the last 2 digits (any number modulo 100 will return the final 2 digits).

Resources