I'm trying to define a function that does A if there's an even number of dollar signs (in my buffer), and B if there's an odd number of dollar signs. However, I'm unsure how to count the number of dollar signs, and then report that number for defining the function. For instance, entering
:%s/\$//gn
will spit out this number on the status line. But how can one apply the result for defining a function?
Based on #DaveNewman's comment, you may write:
:%s/\$//gn | let i = split(v:statusmsg)[0] | if i % 2 | ... | else | ... | endif
Related
This is my very first question linking to my first Python project.
To put it simple, I have 2 columns of data in Excel like this (first 6 rows):
destination_area | destination_code
SG37.D0 | SG37.D
SG30.C0 | SG30.C
SG4.A3.P | SG4.A
SG15.C16 | SG15.C
SG35.D02 | SG35.D
SG8.A5.BC | SG8.A
So in Excel, I'm using a function to get destination code by finding first "." in the cell & return all characters from the left of it, plus 1 character:
=IfError(left(E2,search(".",E2)+1),"")
Now I want to execute it using str.extract
df1['destination_code'] = df1['destination_area'].str.extract(r"(?=(.*[0-9][.][A-Z]))", expand = False)
print(df1['destination_area'].head(6),df1['destination_code'].head(6))
I almost got what I need but the code still recognize those that have more than 1 "."
destination_area | destination_code
SG37.D0 | SG37.D
SG30.C0 | SG30.C
SG4.A3.P | SG4.A3.P
SG15.C16 | SG15.C
SG35.D02 | SG35.D
SG8.A5.BC | SG8.A5.BC
I recognize that my regex is understanding the pattern of {a number + "." + a letter}, which returns all characters for the cases of "SG4.A3.P" and "SG8.A5.BC".
So how to modify my code? Or any better way to perform the code like how Excel does? Thanks in advance
No need in lookahead. Use
df1['destination_code'] = df1['destination_area'].str.extract(r"^([^.]+\..)", expand=False)
See proof. Mind the capturing group, it is enough here to return the value you need.
Explanation:
--------------------------------------------------------------------------------
^ the beginning of the string
--------------------------------------------------------------------------------
( group and capture to \1:
--------------------------------------------------------------------------------
[^.]+ any character except: '.' (1 or more
times (matching the most amount
possible))
--------------------------------------------------------------------------------
\. '.'
--------------------------------------------------------------------------------
. any character except \n
--------------------------------------------------------------------------------
) end of \1
Given the following examples,
16A6
ECCB15
I would only like to extract the last number or numbers from the string value. So the end result that I'm looking for is:
6
15
I've been trying to find a way, but can't seem to find the correct one.
Use thisformula:
=MID(A1,AGGREGATE(14,7,ROW($Z$1:INDEX($ZZ:$ZZ,LEN(A1)))/(NOT(ISNUMBER(--MID(A1,ROW($Z$1:INDEX($ZZ:$ZZ,LEN(A1))),1)))),1)+1,LEN(A1))
Try this:
=--RIGHT(A2,SUMPRODUCT(--ISNUMBER(--RIGHT(SUBSTITUTE(A2,"E",";"),ROW(INDIRECT("1:"&LEN(A2)))))))
or this (avoid using INDIRECT):
=--RIGHT(A2,SUMPRODUCT(--ISNUMBER(--RIGHT(SUBSTITUTE(A2,"E",";"),ROW($A$1:INDEX($A:$A,LEN(A2)))))))
Replace A2 in the above formula to suit your case.
Here are the data for testing:
| String |
|-----------|
| 16A6 |
| ECCB15 |
| BATT5A6 |
| 16 |
| A1B2C3E0 |
| 16E |
| TEST00004 |
I have an even shorter version: --RIGHT(A2,SUMPRODUCT(--ISNUMBER(--RIGHT(SUBSTITUTE(A2,"E",";"),ROW(INDIRECT("1:"&LEN(A2)))))))
The difference is the use of SUBSTITUTE in my final formula. I used SUBSTITUTE to replace letter E with a symbol because in the fifth string in the above list, the RIGHT function in my formula will return the following: {"0";"E0";"3E0";"C3E0";"2C3E0";"B2C3E0";"1B2C3E0";"A1B2C3E0"} where the third string 3E0 will return TRUE by ISNUMBER function, and this will result in an incorrect answer. Therefore I need to get rid of letter E first.
Let me know if you have any questions. Cheers :)
I'm trying to work with manually inserted strings in SAS and I need to remove specific special characters (maybe by inserting a list of them) without removing blank spaces between words.
I've found a possible solution with a combination of compbl and transtrn to remove special characters and substitute them with blanks, reduced to one by compbl but this requires multiple steps.
I'm wondering if there is a function that allows me to do this in a single step. I've tried with the compress function (with the 'k' modifier to keep only letters and digits) but it removes blanks between words.
I'd like to go from a string like this one:
O'()n?e /, ^P.iece
To:
One Piece
With a single blank between the two words.
If someone can help me it would be awesome!
Use the next tags for compress function:
k -- Keep chars instead replace it
a -- Alphabetic chars
s -- Space characters
d -- Digits
And after it, use function COMPBL.
Code:
data have;
value="O'()n?e /, ^P.iece";
run;
data want;
set have;
value_want=COMPBL((compress(value,,"kasd"));
run;
So:
+--------------------+------------+
| value | value_want |
+--------------------+------------+
| O'()n?e /, ^P.iece | One Piece |
+--------------------+------------+
You could use regex and prxchage.
data have;
value="O'()n?e /, ^P.iece";
run;
data want;
set have;
value_want=value_want=prxchange("s/\s\s+/ /",-1,prxchange("s/[^a-zA-Z0-9\s]*//",-1,value));
run;
Result:
+--------------------+------------+
| value | value_want |
+--------------------+------------+
| O'()n?e /, ^P.iece | One Piece |
+--------------------+------------+
I've searched for a while, but it looks like all the examples I find are the opposite of what I need. There are many ways to see if a string with wildcards matches any of the values in an array, but I need to go the other way - I need the array to contain wildcards, and check if the string in the target cell matches any of the match strings in the array, but the match strings can contain wild cards.
To put it in context, I am parsing large log files, and there are many lines I wish to ignore (but not delete); so I have a helper column:
+---+-------+----------------------------------------+----------------------------+
| | A | B | C (filter for = FALSE) | Requirement
+---+-------+----------------------------------------+----------------------------+
| 1 | 11:00 | VPN Status | =COUNTIF(IgnoreList,B1)>0 + Keep
| 2 | 11:05 | Log at event index 118, time index 115 | =COUNTIF(IgnoreList,B2)>0 + Ignore
| 3 | 11:20 | Log at event index 147, time index 208 | =COUNTIF(IgnoreList,B3)>0 + Ignore
+---+-------+----------------------------------------+----------------------------+
I've tried to put wildcards in my IgnoreList range to catch any of the "Log at event" lines:
+--------------------------------------+
| IgnoreList +
+--------------------------------------+
| State Runtime 1 +
| State Runtime 2 +
| State Runtime 3 +
| State Runtime 4 +
| Log at event index *, time index * +
+--------------------------------------+
... but this isn't working.
Does anyone know how to check a cell against an array containing wildcards?
My IgnoreList has 60 entries so far, so testing each cell individually isn't really feasible. I could have 30,000 or more entries in the log, so individual testing will be a lot more formulas than I'd hoped to use. I also don't want to edit the formulae when I add an entry to the IgnoreList.
Thanks for your help!
Use SEARCH, which allows wild card lookups, inside SUMPRODUCT:
=SUMPRODUCT(--ISNUMBER(SEARCH(IgnoreList,B1)))>0
To use COUNTIF one would need to reverse the criteria and wrap in SUMPRODUCT:
=SUMPRODUCT(COUNTIF(B1,IgnoreList))>0
I earlier worked out a good solution for this with the help of the comunity, it works really good but I found out it can only handle suffix words (it dosen't ignore prefix-words).
Formula:
=IF(B1<>"";(LEN(A1)-LEN(SUBSTITUTE(A1;B1&" ";"")))/(LEN(B1)+1)+IF(RIGHT(A1;LEN(B1))=B1;1;0);"")
A contains sentences, multiple words (without punctuation)
B contains the word I want to count the exact frequency of.
C here is there the formula is placed and where I get the result
Sample table:
| A | B | C |
|:-------------------------:|:----:|:--------:|
| boots | shoe | 0 |
----------------------------------------------|
| shoe | shoe | 1 |
----------------------------------------------|
| shoes | shoe | 0 |
----------------------------------------------|
| ladyshoe dogshoe catshoe | shoe | 3 |
----------------------------------------------|
In C-column I am getting correct output in row 1, 2 and 3 but not 4. I want C4 should return 0 and not 3.
The problem is that it makes no match for shoexxxxxxxxxxx (correct) but makes a match for xxxxxxxxxxxshoe (wrong).
I only want the formula to count the exact match for shoe, any other word should not be counted for.
You want this formula:
=IF(B1<>"",(LEN(A1)-LEN(SUBSTITUTE(A1," "&B1&" ","")))/(LEN(B1)+2),"")+IF(A1=B1,1,0)+IF(LEFT(A1,LEN(B1)+1)=B1&" ",1,0)+IF(RIGHT(A1,LEN(B1)+1)=" "&B1,1,0)
I'll denote a space by * to make the following clearer:
There are four cases to consider:
string; the word has no spaces on either side (and is therefore the only word in cell A1
string*; the word appears at the start of a list of words.
*string; the word appears at the end of a list of words.
*string*; the word is in the middle of a list of words.
First we count the number of occurrences of *string*, by substituting "*string*" for "", subtracting the length of the new string from the old one, and dividing by len(string)+2 (which is the length of *string*).
Then we add one more to our count if A1 is exactly string, with no spaces either side.
Then we add one more if A1 starts with string*, and one more if A1 ends with *string.