Objective-C: Find numbers in string
Solution 1
Here's an NSScanner based solution:
// Input
NSString *originalString = @"This is my string. #1234";
// Intermediate
NSString *numberString;
NSScanner *scanner = [NSScanner scannerWithString:originalString];
NSCharacterSet *numbers = [NSCharacterSet characterSetWithCharactersInString:@"0123456789"];
// Throw away characters before the first number.
[scanner scanUpToCharactersFromSet:numbers intoString:NULL];
// Collect numbers.
[scanner scanCharactersFromSet:numbers intoString:&numberString];
// Result.
int number = [numberString integerValue];
(Some of the many) assumptions made here:
- Number digits are 0-9, no sign, no decimal point, no thousand separators, etc. You could add sign characters to the NSCharacterSet if needed.
- There are no digits elsewhere in the string, or if there are they are after the number you want to extract.
- The number won't overflow
int
.
Alternatively you could scan direct to the int
:
[scanner scanUpToCharactersFromSet:numbers intoString:NULL];
int number;
[scanner scanInt:&number];
If the #
marks the start of the number in the string, you could find it by means of:
[scanner scanUpToString:@"#" intoString:NULL];
[scanner setScanLocation:[scanner scanLocation] + 1];
// Now scan for int as before.
Solution 2
Self contained solution:
+ (NSString *)extractNumberFromText:(NSString *)text
{
NSCharacterSet *nonDigitCharacterSet = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];
return [[text componentsSeparatedByCharactersInSet:nonDigitCharacterSet] componentsJoinedByString:@""];
}
Handles the following cases:
- @"1234" → @"1234"
- @"001234" → @"001234"
- @"leading text get removed 001234" → @"001234"
- @"001234 trailing text gets removed" → @"001234"
- @"a0b0c1d2e3f4" → @"001234"
Hope this helps!
Solution 3
You could use the NSRegularExpression class, available since iOS SDK 4.
Bellow a simple code to extract integer numbers ("\d+" regex pattern) :
- (NSArray*) getIntNumbersFromString: (NSString*) string {
NSMutableArray* numberArray = [NSMutableArray new];
NSString* regexPattern = @"\\d+";
NSRegularExpression* regex = [[NSRegularExpression alloc] initWithPattern:regexPattern options:0 error:nil];
NSArray* matches = [regex matchesInString:string options:0 range:NSMakeRange(0, string.length)];
for( NSTextCheckingResult* match in matches) {
NSString* strNumber = [string substringWithRange:match.range];
[numberArray addObject:[NSNumber numberWithInt:strNumber.intValue]];
}
return numberArray;
}
Solution 4
Try this answer from Stack Overflow for a nice piece of C code that will do the trick:
for (int i=0; i<[str length]; i++) {
if (isdigit([str characterAtIndex:i])) {
[strippedString appendFormat:@"%c",[str characterAtIndex:i]];
}
}
Solution 5
By far the best solution! I think regexp would be better, but i kind of sux at it ;-) this filters ALL numbers and concats them together, making a new string. If you want to split multiple numbers change it a bit. And remember that when you use this inside a big loop it costs performance!
NSString *str= @"bla bla bla #123 bla bla 789";
NSMutableString *newStr = [[NSMutableString alloc] init];;
int j = [str length];
for (int i=0; i<j; i++) {
if ([str characterAtIndex:i] >=48 && [str characterAtIndex:i] <=59) {
[newStr appendFormat:@"%c",[str characterAtIndex:i]];
}
}
NSLog(@"%@ as int:%i", newStr, [newStr intValue]);
Nic Hubbard
Updated on October 17, 2020Comments
-
Nic Hubbard over 3 years
I have a string that contains words as well as a number. How can I extract that number from the string?
NSString *str = @"This is my string. #1234";
I would like to be able to strip out 1234 as an int. The string will have different numbers and words each time I search it.
Ideas?
-
Alex over 13 yearsNSPredicate regular expression matching doesn't work on iOS SDK.
-
Daniel Farrell over 13 yearsOh. Thanks, I didn't know that (spend most of my time in MacOS world).
-
Nic Hubbard over 13 yearsGreat solution, this is just what I needed!
-
Soumalya Banerjee over 11 yearsAwesome. Great solution. Thanks.
-
Jignesh B almost 10 yearsif i have multiple number at different place in string then it's return only first number
-
ThomasW over 9 years
NSPredicate
has been part of the iOS SDK since iOS 3.0. -
Yi Jiang almost 9 yearsThis is the best and decent answer in this post. It is better than accepted answer.
-
Yi Jiang almost 9 yearsRegular Expression is powerful. But in this simple case, I think @Zorayr 's answer is the best.
-
Zorayr almost 9 yearsI wouldn't recommend using a c-style for loop here; this could cause a significant lag on larger strings, especially if executed on the main thread.
-
Zorayr almost 9 yearsRegardless of my answer, I think using regex here might be an overkill and a bit more of a maintenance hazard; no one really understands regex and it's hard to debug.
-
Farlei Heinen almost 9 years@Zorayr : I agree that it maybe is a little overkill, but I don't think it's a maintenance hazard. Actually it's really easy to add new functionality and a developer can reuse the pattern in any language that accepts regex.
-
Farlei Heinen almost 9 yearsI add an example to make my answer more clear. It work for integer values. To expand to float values use this pattern: @"[\\d[.]]+"
-
CyberMew over 7 yearsIs it possible to strip the leading zeros as well?
-
Marcus Adams about 6 yearsVery nice. Don't fear the regex.