Remove all non-numeric characters from an NSString, keeping spaces - ios

I am trying to remove all of the non-numeric characters from an NSString, but I also need to keep the spaces. Here is what I have been using.
NSString *strippedBbox = [_bbox stringByReplacingOccurrencesOfString:#"[^0-9]" withString:#"" options:NSRegularExpressionSearch range:NSMakeRange(0, [_bbox length])];
If I give it a NSString of Test 333 9599 999 It will return 3339599999 but I need to keep the spaces in.
How can I do this?

Easily done by creating a character set of characters you want to keep and using invertedSet to create an "all others" set. Then split the string into an array separated by any characters in this set and reassemble the string again. Sounds complicated but very simple to implement:
NSCharacterSet *setToRemove =
[NSCharacterSet characterSetWithCharactersInString:#"0123456789 "];
NSCharacterSet *setToKeep = [setToRemove invertedSet];
NSString *newString =
[[someString componentsSeparatedByCharactersInSet:setToKeep]
componentsJoinedByString:#""];
result: 333 9599 99

You could alter your first regex to include a space after the 9:
In swift:
var str = "test Test 333 9599 999";
val strippedStr = str.stringByReplacingOccurrencesOfString("[^0-9 ]", withString: "", options: NSStringCompareOptions.RegularExpressionSearch, range:nil);
// strippedStr = " 33 9599 999"
While this leaves the leading space, you could apply a whitespace trimming to deal with that:
strippedStr.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet())
// strippedStr = "33 9599 999"

// Our test string
NSString* _bbox = #"Test 333 9599 999";
// Remove everything except numeric digits and spaces
NSString *strippedBbox = [_bbox stringByReplacingOccurrencesOfString:#"[^\\d ]" withString:#"" options:NSRegularExpressionSearch range:NSMakeRange(0, [_bbox length])];
// (Optional) Trim spaces on either end, but keep spaces in the middle
strippedBbox = [strippedBbox stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
// Print result
NSLog(#"%#", strippedBbox);
This prints 333 9599 999, which I think is what you're after. It also removes non numeric characters that may be in the middle of the string, such as parentheses.

For Swift 3.0.1 folks
var str = "1 3 6 .599.188-99 "
str.replacingOccurrences(of: "[^0-9]", with: "", options: .regularExpression, range: nil)
Output: "13659918899"
This also trim spaces from string

try using NSScanner
NSString *originalString = #"(123) 123123 abc";
NSMutableString *strippedString = [NSMutableString
stringWithCapacity:originalString.length];
NSScanner *scanner = [NSScanner scannerWithString:originalString];
NSCharacterSet *numbers = [NSCharacterSet
characterSetWithCharactersInString:#"0123456789 "];
while ([scanner isAtEnd] == NO) {
NSString *buffer;
if ([scanner scanCharactersFromSet:numbers intoString:&buffer]) {
[strippedString appendString:buffer];
} else {
[scanner setScanLocation:([scanner scanLocation] + 1)];
}
}
NSLog(#"%#", strippedString); // "123123123"

NSMutableString strippedBbox = [_bbox mutableCopy];
NSCharacterSet* charSet = [NSCharacterSet characterSetWithCharactersInString:#"1234567890 "].invertedSet;
NSUInteger start = 0;
NSUInteger length = _bbox.length;
while(length > 0)
{
NSRange range = [strippedBbox rangeOfCharacterFromSet:charSet options:0 range:NSMakeRange(start, length)];
if(range.location == NSNotFound)
{
break;
}
start += (range.location + range.length);
length -= range.length;
[strippedBbox replaceCharactersInRange:range withString:#""];
}

In brief, you can use NSCharacterSet to examine only those chars that are interesting to you and ignore the rest.
- (void) stripper {
NSString *inString = #"A1 B2 C3 D4";
NSString *outString = #"";
for (int i = 0; i < inString.length; i++) {
if ([[NSCharacterSet whitespaceCharacterSet] characterIsMember:[inString characterAtIndex:i]] || [[NSCharacterSet decimalDigitCharacterSet] characterIsMember:[inString characterAtIndex:i]]) {
outString = [outString stringByAppendingString:[NSString stringWithFormat:#"%c",[inString characterAtIndex:i]]];
}
}
}

Related

Create Regular Expression for specified string in objective c

My NSString like below
#"[o=uid=35=] hghk\u00c2\u00a0 [o=uid=30=] [o=uid=35=] cong."
I need to create regular expression which search numeric values (e.g in first square brackets there is 35 in second there is 30 like this) in between square parenthesis. How could i achieve this task. Is there any alternate way to search numeric values in between square parenthesis? Please help me to short resolve from this. your help would be appreciable.
Using NSRegularExpression,
NSString* strSource = #"[o=uid=35=] hghk\u00c2\u00a0 [o=uid=30=] [o=uid=35=] cong.";
NSError* errRegex = NULL;
NSRegularExpression* regex = [NSRegularExpression
regularExpressionWithPattern:#"uid=([0-9]+)"
options:NSRegularExpressionCaseInsensitive
error:&errRegex];
NSUInteger countMatches = [regex numberOfMatchesInString:strSource
options:0
range:NSMakeRange(0, [strSource length])];
NSLog(#"Number of Matches: %ld", (unsigned long)countMatches);
[regex enumerateMatchesInString:strSource options:0
range:NSMakeRange(0, [strSource length])
usingBlock:^(NSTextCheckingResult* match,
NSMatchingFlags flags, BOOL* stop) {
NSLog(#"Ranges: %ld", (unsigned long)[match numberOfRanges]);
NSString *matchFull = [strSource substringWithRange:[match range]];
NSLog(#"Match: %#", matchFull);
for (int i = 0; i < [match numberOfRanges]; i++) {
NSLog(#"\tRange %i: %#", i,
[strSource substringWithRange:[match rangeAtIndex:i]]);
}
}];
if (errRegex) {
NSLog(#"%#", errRegex);
}
http://regexpal.com/
use above link to check the expression
\b[0-9]+
to find all the integer values
([0-9])+
it works.
You can build a regular expression like this:
uid=([0-9]+)
This will find any numbers after "uid=" sequence in a string. The value of the number will be available in "match 1", since it is put in parentheses. You can try out this Regex interactively with http://rubular.com/.
if you just want numeric value then you can try this
NSString *mainString = #"[o=uid=35=] hghk\u00c2\u00a0 [o=uid=30=] [o=uid=35=] cong.";
NSArray *arr = [mainString componentsSeparatedByString:#"="];
for(int i=0;i<arr.count;i++)
{
NSString *newString = arr[i];
NSCharacterSet* notDigits = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];
if ([newString rangeOfCharacterFromSet:notDigits].location == NSNotFound)
{
NSLog(#"%#",newString);
// newString consists only of the digits 0 through 9
}
}
Here is my code,it works perfectly..we can check easily below array contains object(numbers between '[' and ']') or not without using any regex.
NSString *tmpTxt = #"[o=uid=35=] hghk\u00c2\u00a0 [o=uid=30=] [o=uid=35=] cong.";
NSString*splittxt=tmpTxt;
NSMutableArray*array=[[NSMutableArray alloc]init];
for (int i=0; i<i+1; i++) {
NSRange r1 = [splittxt rangeOfString:#"["];
NSRange r2 = [splittxt rangeOfString:#"]"];
NSRange rsub=NSMakeRange(r1.location + r1.length-1, r2.location - r1.location - r1.length+2);
if (rsub.length >2 ){
NSCharacterSet *AllowedChars = [[NSCharacterSet characterSetWithCharactersInString:#"1234567890"] invertedSet];
NSString*stringg=[splittxt substringWithRange:rsub];
stringg = [[stringg componentsSeparatedByCharactersInSet:AllowedChars] componentsJoinedByString:#""];
[array addObject:stringg];
}
else
{
break;
}
splittxt=[splittxt stringByReplacingCharactersInRange:rsub withString:#""];
}
NSLog(#"%#",array);
}
the array value is
(
35,
30,
35
)

Finding word in NSString and checking before and after character this word?

How to find word in NSString and check characters before and after this word?
"This pattern has two parts separated by the"
How to find tern and how to check the character before and after
Before word character:"t"
After word character:" "
You can use NSScanner to get indexes of these two characters.
Example:
NSString *string = #"tern";
NSScanner *scanner = [[NSScanner alloc] initWithString:#"This pattern has two parts separated by the"];
[scanner scanUpToString:string intoString:nil];
NSUInteger indexOfChar1 = scanner.scanLocation - 1;
NSUInteger indexOfChar2 = scanner.scanLocation + string.length;
You can also use a rangeOfString method:
Example:
NSRange range = [sourceString rangeOfString:stringToLookFor];
NSUInteger indexOfChar1 = range.location - 1;
NSUInteger indexOfChar2 = range.location +range.length + 1;
Then, when you have indexes, getting the characters is easy:
NSString *firstCharacter = [sourceString substringWithRange:NSMakeRange(indexOfChar1, 1)];
NSString *secondCharacter = [sourceString substringWithRange:NSMakeRange(indexOfChar2, 1)];
Hope this helps.
Here is an implementation using Regular Expressions
NSString *testString= #"This pattern has two parts separated by the";
NSString *regexString = #"(.)(tern)(.)";
NSRegularExpression* exp = [NSRegularExpression
regularExpressionWithPattern:regexString
options:NSRegularExpressionSearch error:&error];
if (error) {
NSLog(#"%#", error);
} else {
NSTextCheckingResult* result = [exp firstMatchInString:testString options:0 range:NSMakeRange(0, [testString length] ) ];
if (result) {
NSRange groupOne = [result rangeAtIndex:1]; // 0 is the WHOLE string.
NSRange groupTwo = [result rangeAtIndex:2];
NSRange groupThree = [result rangeAtIndex:3];
NSLog(#"[%#][%#][%#]",
[testString substringWithRange:groupOne],
[testString substringWithRange:groupTwo],
[testString substringWithRange:groupThree] );
}
}
Results:
[t][tern][ ]
Its better to get pre and post character in NSString to avoid handling of unicode characters.
NSString * testString = #"This pattern has two parts separated by the";
NSString * preString;
NSString * postString;
NSUInteger maxRange;
NSRange range = [testString rangeOfString:#"tern"];
if(range.location == NSNotFound){
NSLog(#"Not found");
return;
}
if (range.location==0) {
preString=nil;
}
else{
preString = [testString substringWithRange:NSMakeRange(range.location-1,1)];
}
maxRange = NSMaxRange(range);
if ( maxRange >=testString.length ) {
postString = nil;
}
else{
postString = [testString substringWithRange:NSMakeRange(range.location+range.length, 1)];
}

Truncate string containing emoji or unicode characters at word or character boundaries

How can I truncate a string at a given length without annihilating a unicode character that might be smack in the middle of my length? How can one determine the index of the beginning of a unicode character in a string so that I can avoid creating ugly strings. The square with half of an A visible is the location of another emoji character which has been truncated.
-(NSMutableAttributedString*)constructStatusAttributedStringWithRange:(CFRange)range
NSString *original = [_postDictionay objectForKey:#"message"];
NSMutableString *truncated = [NSMutableString string];
NSArray *components = [original componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
for(int x=0; x<[components count]; x++)
{
//If the truncated string is still shorter then the range desired. (leave space for ...)
if([truncated length]+[[components objectAtIndex:x] length]<range.length-3)
{
//Just checking if its the first word
if([truncated length]==0 && x==0)
{
//start off the string
[truncated appendString:[components objectAtIndex:0]];
}
else
{
//append a new word to the string
[truncated appendFormat:#" %#",[components objectAtIndex:x]];
}
}
else
{
x=[components count];
}
}
if([truncated length]==0 || [truncated length]< range.length-20)
{
truncated = [NSMutableString stringWithString:[original substringWithRange:NSMakeRange(range.location, range.length-3)]];
}
[truncated appendString:#"..."];
NSMutableAttributedString *statusString = [[NSMutableAttributedString alloc]initWithString:truncated];
[statusString addAttribute:(id)kCTFontAttributeName value:[StyleSingleton streamStatusFont] range:NSMakeRange(0, [statusString length])];
[statusString addAttribute:(id)kCTForegroundColorAttributeName value:(id)[StyleSingleton streamStatusColor].CGColor range:NSMakeRange(0, [statusString length])];
return statusString;
}
UPDATE Thanks to the answer, was able to use one simple function for my needs!
-(NSMutableAttributedString*)constructStatusAttributedStringWithRange:(CFRange)range
{
NSString *original = [_postDictionay objectForKey:#"message"];
NSMutableString *truncated = [NSMutableString stringWithString:[original substringWithRange:[original rangeOfComposedCharacterSequencesForRange:NSMakeRange(range.location, range.length-3)]]];
[truncated appendString:#"..."];
NSMutableAttributedString *statusString = [[NSMutableAttributedString alloc]initWithString:truncated];
[statusString addAttribute:(id)kCTFontAttributeName value:[StyleSingleton streamStatusFont] range:NSMakeRange(0, [statusString length])];
[statusString addAttribute:(id)kCTForegroundColorAttributeName value:(id)[StyleSingleton streamStatusColor].CGColor range:NSMakeRange(0, [statusString length])];
return statusString;
}
NSString has a method rangeOfComposedCharacterSequencesForRange that you can use to find the enclosing range in the string that contains only complete composed characters. For example
NSString *s = #"😄";
NSRange r = [s rangeOfComposedCharacterSequencesForRange:NSMakeRange(0, 1)];
gives the range { 0, 2 } because the Emoji character is stored as two UTF-16 characters (surrogate pair) in the string.
Remark: You could also check if you can simplify your first loop by using
enumerateSubstringsInRange:options:usingBlock
with the NSStringEnumerationByWords option.
"truncate a string at a given length" <-- Do you mean length as in byte length or length as in number of characters? If the latter, then a simple substringToIndex: will suffice (check the bounds first though). If the former, then I'm afraid you'll have to do something like:
NSString *TruncateString(NSString *original, NSUInteger maxBytesToRead, NSStringEncoding targetEncoding) {
NSMutableString *truncatedString = [NSMutableString string];
NSUInteger bytesRead = 0;
NSUInteger charIdx = 0;
while (bytesRead < maxBytesToRead && charIdx < [original length]) {
NSString *character = [original substringWithRange:NSMakeRange(charIdx++, 1)];
bytesRead += [character lengthOfBytesUsingEncoding:targetEncoding];
if (bytesRead <= maxBytesToRead)
[truncatedString appendString:character];
}
return truncatedString;
}
EDIT: Your code can be rewritten as follows:
NSString *original = [_postDictionay objectForKey:#"message"];
NSArray *characters = [[original componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"SELF != ''"]];
NSArray *truncatedCharacters = [characters subarrayWithRange:range];
NSString *truncated = [NSString stringWithFormat:#"%#...", [truncatedCharacters componentsJoinedByString:#" "]];

How do I get the substring between braces?

I have a string as this.
NSString *myString = #"{53} balloons";
How do I get the substring 53 ?
NSString *myString = #"{53} balloons";
NSRange start = [myString rangeOfString:#"{"];
NSRange end = [myString rangeOfString:#"}"];
if (start.location != NSNotFound && end.location != NSNotFound && end.location > start.location) {
NSString *betweenBraces = [myString substringWithRange:NSMakeRange(start.location+1, end.location-(start.location+1))];
}
edit: Added range check, thx to Keab42 - good point.
Here is what I did.
NSString *myString = #"{53} balloons";
NSCharacterSet *delimiters = [NSCharacterSet characterSetWithCharactersInString:#"{}"];
NSArray *splitString = [myString componentsSeparatedByCharactersInSet:delimiters];
NSString *substring = [splitString objectAtIndex:1];
the substring is 53.
For Swift 4.2:
if let r1 = string.range(of: "{")?.upperBound,
let r2 = string.range(of: "}")?.lowerBound {
print (String(string[r1..<r2]))
}
You can use a regular expression to get the number between the braces. It might seem a bit complicated but the plus side is that it will find multiple numbers and the position of the number doesn't matter.
Swift 4.2:
let searchText = "{53} balloons {12} clowns {123} sparklers"
let regex = try NSRegularExpression(pattern: "\\{(\\d+)\\}", options: [])
let matches = regex.matches(in: searchText, options: [], range: NSRange(searchText.startIndex..., in: searchText))
matches.compactMap { Range($0.range(at: 1), in: searchText) }
.forEach { print("Number: \(searchText[$0])") }
Objective-C:
NSString *searchText = #"{53} balloons {12} clowns {123} sparklers";
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"\\{(\\d+)\\}"
options:0
error:nil];
NSArray *matches = [regex matchesInString:searchText
options:0
range:NSMakeRange(0, searchText.length)];
for (NSTextCheckingResult *r in matches)
{
NSRange numberRange = [r rangeAtIndex:1];
NSLog(#"Number: %#", [searchText substringWithRange:numberRange]);
}
This will print out:
Number: 53
Number: 12
Number: 123
Try this code.
NSString *myString = #"{53} balloons";
NSString *value = [myString substringWithRange:NSMakeRange(1,2)];
For Swift 2.1 :-
var start = strData?.rangeOfString("{")
var end = strData?.rangeOfString("}")
if (start!.location != NSNotFound && end!.location != NSNotFound && end!.location > start!.location) {
var betweenBraces = strData?.substringWithRange(NSMakeRange(start!.location + 1, end!.location-(start!.location + 1)))
print(betweenBraces)
}
I guess, your a looking for the NSScanner class, at least if you are addressing a general case. Have a look in Apples documentation.
Search the location for "{" and "}".
Take substring between those index.
Checked with any number of data:
NSString *str = #"{53} balloons";
NSArray* strary = [str componentsSeparatedByString: #"}"];
NSString* str1 = [strary objectAtIndex: 0];
NSString *str2 = [str1 stringByReplacingOccurrencesOfString:#"{" withString:#""];
NSLog(#"number = %#",str2);
Another method is
NSString *tmpStr = #"{53} balloons";
NSRange r1 = [tmpStr rangeOfString:#"{"];
NSRange r2 = [tmpStr rangeOfString:#"}"];
NSRange rSub = NSMakeRange(r1.location + r1.length, r2.location - r1.location - r1.length);
NSString *subString = [tmpStr substringWithRange:rSub];
If you don't know how many digits there will be, but you know it will always be enclosed with curly braces try this:
NSString *myString = #"{53} balloons";
NSRange startRange = [myString rangeOfString:#"{"];
NSRange endRange = [myString rangeOfString:#"}"];
if (startRange.location != NSNotFound && endRange.location != NSNotFound && endRange.location > startRange.location) {
NSString *value = [myString substringWithRange:NSMakeRange(startRange.location,endRange.ocation - startRange.location)];
}
There's probably a more efficient way to do it though.

Finding first letter in NSString and counting backwards

I'm new to IOS, and was looking for some guidance.
I have a long NSString that I'm parsing out. The beginning may have a few characters of garbage (can be any non-letter character) then 11 digits or spaces, then a single letter (A-Z). I need to get the location of the letter, and get the substring that is 11 characters behind the letter to 1 character behind the letter.
Can anyone give me some guidance on how to do that?
Example: '!!2553072 C'
and I want : '53072 '
You can accomplish this with the regex pattern: (.{11})\b[A-Z]\b
The (.{11}) will grab any 11 characters and the \b[A-Z]\b will look for a single character on a word boundary, meaning it will be surrounded by spaces or at the end of the string. If characters can follow the C in your example then remove the last \b. This can be accomplished in Objective-C like so:
NSError *error;
NSString *example = #"!!2553072 C";
NSRegularExpression *regex = [NSRegularExpression
regularExpressionWithPattern:#"(.{11})\\b[A-Z]\\b"
options:NSRegularExpressionCaseInsensitive
error:&error];
if(!regex)
{
//handle error
}
NSTextCheckingResult *match = [regex firstMatchInString:example
options:0
range:NSMakeRange(0, [example length])];
if(match)
{
NSLog(#"match: %#", [example substringWithRange:[match rangeAtIndex:1]]);
}
There may be a more elegant way to do this involving regular expressions or some Objective-C wizardry, but here's a straightforward solution (personally tested).
-(NSString *)getStringContent:(NSString *)input
{
NSString *substr = nil;
NSRange singleLetter = [input rangeOfCharacterFromSet:[NSCharacterSet letterCharacterSet]];
if(singleLetter.location != NSNotFound)
{
NSInteger startIndex = singleLetter.location - 11;
NSRange substringRange = NSMakeRange(start, 11);
substr = [tester substringWithRange:substringRange];
}
return substr;
}
You can use NSCharacterSets to split up the string, then take the first remaining component (consisting of your garbage and digits) and get a substring of that. For example (not compiled, not tested):
- (NSString *)parseString:(NSString *)myString {
NSCharacterSet *letters = [NSCharacterSet letterCharacterSet];
NSArray *components = [myString componentsSeparatedByCharactersInSet:letters];
assert(components.count > 0);
NSString *prefix = components[0]; // assuming relatively new Xcode
return [prefix substringFromIndex:(prefix.length - 11)];
}
//to get rid of all non-Digits in a NSString
NSString *customerphone = CustomerPhone.text;
int phonelength = [customerphone length];
NSRange customersearchRange = NSMakeRange(0, phonelength);
for (int i =0; i < phonelength;i++)
{
const unichar c = [customerphone characterAtIndex:i];
NSString* onechar = [NSString stringWithCharacters:&c length:1];
if(!isdigit(c))
{
customerphone = [customerphone stringByReplacingOccurrencesOfString:onechar withString:#"*" options:0 range:customersearchRange];
}
}
NSString *PhoneAllNumbers = [customerphone stringByReplacingOccurrencesOfString:#"*" withString:#"" options:0 range:customersearchRange];

Resources