How to Get Percentage From a NSString - Objective C - objective-c

I would like to get a substring for a NSString that contains a percentage value.
For example:
1. Get 10% off with this item.
2. 55% off when you purchase this.
function should return 10% and 55% respectively.
I am using regex in Java \\d+%
I don't know how to do the same in objective c.
I have searched it but I am a bit lost.

You should be able to use NSRegularExpression to execute the same regex that you use in java. There is a good tutorial for NSRegularExpression here.
https://www.raywenderlich.com/30288/nsregularexpression-tutorial-and-cheat-sheet
I was able to accomplish it with this code:
NSString *string = #"10% off with this item";
NSError *error = nil;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"\\d+%" options:0 error:&error];
NSTextCheckingResult *result = [regex firstMatchInString:string options:0 range:NSMakeRange(0, [string length])];
NSString *substring = [string substringWithRange:result.range];
NSLog(#"%#", substring); // 10%
The key is in the TextCheckingResult. It contains the NSRange for the match in the original string so you can grab a substring of the match.

Related

Regular expression substitution problem in Objective-C

Trying to capitalize all tags and running into trouble with substitution. Any idea why "upperCaseString" method isn't working?
NSError *error = nil;
NSMutableString *stringToCap = [NSMutableString stringWithString:#"<kaboom>stuff</kaboom>"];
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"(</?[a-zA-Z].*?>)" options:NSRegularExpressionCaseInsensitive error:&error];
NSMutableString *modifiedString = [NSMutableString stringWithString:[regex stringByReplacingMatchesInString:stringToCap options:0 range:NSMakeRange(0, [stringToCap length]) withTemplate:#"$1".uppercaseString]];
NSLog(#"%#", modifiedString);
Produces: <kaboom>stuff</kaboom> when I expect <KABOOM>stuff</KABOOM>
stringByReplacingMatchesInString:options:range:withTemplate: doesn't work like that, the type of the last argument is just NSString and the string you are passing is the result of the expression #"$1".uppercaseString – which is just #"$1".
A possible algorithm (pseudo code):
for NSTextCheckingResult *match in [regex matchesInString:... options:... range:...] do
extract the substring at match.range from modified string
uppercase it
replace the substring at match.range with uppercased result

Regular expression to grub usernames from string

i need to find usernames (like twitter ones) in strings, for example, if the string is:
"Hello, #username! How are you? And #username2??"
I want to isolate/extract #username and #username2
Do you know how to do it in Objective-C, i found this for Python regex for Twitter username but does not work for me
I tried it like this, but is not working:
NSString *comment = #"Hello, #username! How are you? And #username2??";
NSError *error = nil;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"(?<=^|(?<=[^a-zA-Z0-9-\\.]))#([A-Za-z]+[A-Za-z0-9-]+)" options:0 error:&error];
NSArray *matches = [regex matchesInString:comment options:0 range:NSMakeRange(0, comment.length)];
for (NSTextCheckingResult *match in matches) {
NSRange wordRange = [match rangeAtIndex:1];
NSString *username = [comment substringWithRange:wordRange];
NSLog(#"searchUsersInComment result --> %#", username);
}
(?<=^|(?<=[^a-zA-Z0-9-\\.]))#([A-Za-z]+[A-Za-z0-9-]+) is to neglect emails and grab only usernames, as your string doesn't contain any emails, you should just use #([A-Za-z]+[A-Za-z0-9-]+)
Your regex is wrong. You need to modify it to:
NSString *comment = #"Hello, #username! How are you? And #username2??";
NSError *error = nil;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"#([A-Za-z]+[A-Za-z0-9-]+)" options:0 error:&error];
NSArray *matches = [regex matchesInString:comment options:0 range:NSMakeRange(0, comment.length)];
for (NSTextCheckingResult *match in matches) {
NSRange wordRange = [match rangeAtIndex:1];
NSString *username = [comment substringWithRange:wordRange];
NSLog(#"searchUsersInComment result --> %#", username);
}
FYI: Any subpattern inside a pair of parentheses will be captured as a group. In practice, this can be used to extract information like phone numbers or emails from all sorts of data.
Imagine for example that you had a command line tool to list all the image files you have in the cloud. You could then use a pattern such as ^(IMG\d+.png)$ to capture and extract the full filename, but if you only wanted to capture the filename without the extension, you could use the pattern ^(IMG\d+).png$ which only captures the part before the period.
I would suggest you to read about regex strings: http://regexone.com/lesson/capturing_groups

RegEx (replaceMatchesInString) does not work

Why does this RegEx with replaceMatchesInString return only "+" instead of "+123"?
NString *phoneNumberCleaned = [NSString stringWithFormat:#"++00123"];
NSString *strRegExPhoneNumberPrefixWrong = #"^([+0]*)\\d*$";
NSRegularExpression *regEx = [NSRegularExpression regularExpressionWithPattern:strRegEx options:0 error:nil];
[regEx replaceMatchesInString:phoneNumberCleaned options:0 range:NSMakeRange(0, [phoneNumberCleaned length]) withTemplate:#"+"];
return phoneNumberCleaned;
Thanks
NSString *string = #"++00123";
NSError *error = nil;
NSRegularExpression *regex = [NSRegularExpression
regularExpressionWithPattern:#"^[+0]+(?=\\d*)"
options:NSRegularExpressionCaseInsensitive
error:&error];
NSString *modifiedString = [regex
stringByReplacingMatchesInString:string
options:0
range:NSMakeRange(0, [string length])
withTemplate:#"+"];
return modifiedString;
The problem with your Regex was that ^([+0]*)\\d*$ is also matching the \d* which means, that it also gets replaced (you'd think that it would only replace your capture group, but evidently that isn't so). So you were essentialy replacing any string that matches the above pattern (which was including any trailing numbers), which in your case was the entire number.
What I used in my answer is called a positive lookahead.
^[+0]+(?=\\d*)$
The lookahead basically means that you're looking for zero or more + or 0 that are followed by zero or more digits EXCLUDING the digits from the match. So you only replace the zeroes and pluses, not the digits following them.

String Trimming with Certain keyword

I have a string like below.
<br><br><br><br><br> SomeHtmlString <br><br><br><br><br>
I want to remove br tags like trim function preserving middle br tags in SomeHtmlString.
Is there any function to do this shortly?
e.g.
<br><br><br>test1<br><br>test2<br><br><br><br>
to
test1<br><br>test2
Here is a method using regular expressions. It matches only one at a time and replaces that either at the beginning of end of the string.
NSMutableString *replaceMe = [[NSMutableString alloc ]
initWithString:#"<br><br > <br > test<br>test2<br><br>"];
NSError *error = NULL;
NSRegularExpression *regex = [NSRegularExpression
regularExpressionWithPattern:#"^ *<br *> *"
options:NSRegularExpressionCaseInsensitive
error:&error];
do {
;
} while ([regex replaceMatchesInString:replaceMe options:NSMatchingCompleted range:NSMakeRange(0, replaceMe.length) withTemplate:#""] != 0);
regex = [NSRegularExpression
regularExpressionWithPattern:#" *<br *> *$"
options:NSRegularExpressionCaseInsensitive
error:&error];
do {
;
} while ([regex replaceMatchesInString:replaceMe options:NSMatchingCompleted range:NSMakeRange(0, replaceMe.length) withTemplate:#""] != 0);
NSLog(#"string=%#", replaceMe);
and that does strip "<br><br > <br > test<br>test2<br><br>" down to test<br>test2.
It's probably not the neatest solution but it is very easy to modify to match different expressions, with different whitespace, for example.
It's also possible to use the regular expressions to match several <br>s in one go:
NSRegularExpression *regex = [NSRegularExpression
regularExpressionWithPattern:#"^ *(<br *> *)+"
options:NSRegularExpressionCaseInsensitive
error:&error];
[regex replaceMatchesInString:replaceMe options:NSMatchingCompleted range:NSMakeRange(0, replaceMe.length) withTemplate:#""];
NSRegularExpression *regex = [NSRegularExpression
regularExpressionWithPattern:#" *(<br *> *)+$"
options:NSRegularExpressionCaseInsensitive
error:&error];
[regex replaceMatchesInString:replaceMe options:NSMatchingCompleted range:NSMakeRange(0, replaceMe.length) withTemplate:#""];
which avoids the looping but is a little harder to modify.
You can do this:
NSString* htmlString= #"<br><br><br><br><br> SomeHtmlString <br><br><br><br><br>";
NSString* pureString= [htmlString stringByReplacingOccurrencesOfString: #"<br>" withString: #""];
So you'll have #" SomeHtmlString " in pureString.
You could use this to strip out the unwanted bits:
[yourString stringByReplacingOccurrencesOfString:#"<br>" withString:#""];
Then you would use something like this to remake your string the way you want it:
NSString *newString = [NSString stringWithFormat:#"<br>%#<br>", yourString];
You might also want to look at stringByTrimmingCharactersInSet:
There are so many things you can do with NSString. Check out the Class Reference: https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/Reference/NSString.html
EDIT:
substringToIndex: could be your friend here. You can do this to find out if the first 4 characters of your string consist of the characters you want to remove:
NSString *subString = [yourString substringToIndex:4];
if ([subString isEqualToString:#"<br>"]) {
yourString = [yourString substringFromIndex:4];
}
Then you are creating a new string without those 4 characters. You keep doing this until the first 4 character are not equal to the ones you want to remove.
You can do something similar at the end of your string using substringFromIndex. You will need to know the length of your original string to make sure none of your substrings go out of bounds.
Alternative regular expression rendition:
NSString *input = #"<br><br><br><br><br><br>test<br>test2<br><br><br><br><br><br><br><br><br><br>";
__block NSString *output;
NSError *error;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"^(<br>)*(.*?)(<br>)*$"
options:NSRegularExpressionCaseInsensitive
error:&error];
[regex enumerateMatchesInString:input
options:0
range:NSMakeRange(0, [input length])
usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
NSRange matchRange = [result rangeAtIndex:2];
output = [input substringWithRange:matchRange];
}];
if (output)
NSLog(#"Found: %#", output);

Objective-C NSRegularExpressions, finding first occurrence of numbers in a string

I'm pretty green at regex with Objective-C. I'm having some difficulty with it.
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"\\b([1-9]+)\\b" options:NSRegularExpressionCaseInsensitive error:&regError];
if (regError) {
NSLog(#"%#",regError.localizedDescription);
}
__block NSString *foundModel = nil;
[regex enumerateMatchesInString:self.model options:kNilOptions range:NSMakeRange(0, [self.model length]) usingBlock:^(NSTextCheckingResult *match, NSMatchingFlags flags, BOOL *stop) {
foundModel = [self.model substringWithRange:[match rangeAtIndex:0]];
*stop = YES;
}];
All I'm looking to do is take a string like
150A
And get
150
First the problems with the regex:
You are using word boundaries (\b) which means you are only
looking for a number that is by itself (e.g. 15 but not 150A).
Your number range does not include 0 so it would not capture 150. It needs to be [0-9]+ and better yet use \d+.
So to fix this, if you want to capture any number all you need is \d+. If you want to capture anything that starts with a number then only put the word boundary at the beginning \b\d+.
Now to get the first occurrence you can use -[regex rangeOfFirstMatchInString:options:range:]
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"\\b\\d+" options:NSRegularExpressionCaseInsensitive error:&regError];
if (regError) {
NSLog(#"%#",regError.localizedDescription);
}
NSString *model = #"150A";
NSString *foundModel = nil;
NSRange range = [regex rangeOfFirstMatchInString:model options:kNilOptions range:NSMakeRange(0, [model length])];
if(range.location != NSNotFound)
{
foundModel = [model substringWithRange:range];
}
NSLog(#"Model: %#", foundModel);
What about .*?(\d+).*? ?
Demo:
That would backreference the number and you would be able to use it wherever you want.