我是Objective-C的新手,但在其他更高级的语言方面经验丰富。我想通过删除所有非数字字符来规范化字符串。换句话说,给定输入字符串“206-555-1212”,归一化结果应为“2065551212”。下面的代码片段有效,但鉴于我在其他语言中的经验看起来有点矫枉过正。有没有更好的方法呢?
编辑:输入字符串“(206)555-1212”,“206.555.1212”,“206 555 1212”等也应返回相同的标准化结果。
NSString * normalize(NSString * number)
{
NSString *normalizedNumber = @"";
NSString *tmpString = nil;
NSRange searchRange;
NSRange resultRange;
searchRange.location = 0;
searchRange.length = number.length;
while (0 < searchRange.length)
{
resultRange = [number rangeOfCharacterFromSet:[NSCharacterSet decimalDigitCharacterSet]
options:NSLiteralSearch
range:searchRange];
tmpString = [number substringWithRange:resultRange];
normalizedNumber = [normalizedNumber stringByAppendingString:tmpString];
searchRange.location = resultRange.location + resultRange.length;
searchRange.length = number.length - searchRange.location;
}
return normalizedNumber;
}
答案 0 :(得分:12)
Resh32在their answer中将此代码建议用于类似的问题:
NSString * val = @"(555) 555-555 Office";
NSString * strippedNumber = [val stringByReplacingOccurrencesOfString:@"[^0-9]" withString:@"" options:NSRegularExpressionSearch range:NSMakeRange(0, [val length])];
NSLog(@"%@", strippedNumber);
答案 1 :(得分:8)
所有这些答案都没有解决问题的“删除所有非数字字符”部分。这是一个简单的方法:
NSString *normalize(NSString *number) {
NSMutableCharacterSet *nonNumberCharacterSet = [NSMutableCharacterSet decimalDigitCharacterSet];
[nonNumberCharacterSet invert];
return [[number componentsSeparatedByCharactersInSet:nonNumberCharacterSet] componentsJoinedByString:@""];
}
答案 2 :(得分:1)
我有一个小帮手方法:
+ (NSString *)strip:(NSString *)str keep:(NSString *)chars {
NSCharacterSet *cs = [NSCharacterSet characterSetWithCharactersInString:chars];
NSMutableString *res = [NSMutableString stringWithString:str];
for (int i = [res length] - 1; i >= 0; i--) {
if (![cs characterIsMember:[res characterAtIndex:i]]) {
[res deleteCharactersInRange:NSMakeRange(i, 1)];
}
}
return res;
}
可以像这样调用:
NSString *cleanString = [UtilityClass strip:originalString keep:@"0123456789+*#"];
答案 3 :(得分:1)
即使这个也可以使用:
NSString *s = @"234-1243-123";
NSString *ss=[[s componentsSeparatedByString:@"-"] componentsJoinedByString:@""];
答案 4 :(得分:0)
一个选项是创建一个NSFormatter子类来封装逻辑,或者使用一个开源的子类。 PhoneNumberFormatter看起来很有前途,并允许您删除格式,如下所示:
PhoneNumberFormatter *formatter = [[PhoneNumberFormatter alloc] init];
id objectValue;
NSError *error;
[formatter getObjectValue:&objectValue forString:@"1 (234) 567-8900" errorDescription:&error];
// objectValue = @"12345678900"
答案 5 :(得分:0)
这取决于您的具体目标。
如果您确定所有输入都是xxx-xxx-xxxx
形式,这与removing all the whitespace form a string相同的基本问题(答案类似于已发布的答案),而不是删除你删除-
字符的空格。摘要:使用-[NSString stringByReplacingOccurrencesOfString:withString:]
(-[NSString componentsSeparatedByCharactersInSet:]
在这种情况下略微过度杀戮,但可能足以代替下面的NSScanner
技术。
如果您尝试使用任意格式清理电话号码,那么您使用的方法是合理的,但如the answer to "Remove all but numbers from NSString"中所述,使用NSScanner会更加惯用。另请注意,如果您正在构建一个字符串(就像您的代码那样),那么使用NSMutableString和-appendString:
而不是-[NSString stringByAppendingString:]
会更有效率。
rmaddy's方法在这里也是一个很好的方法,但需要注意的是,它可能最适合作为NSString上的一个类别,其名称遵循Apple的惯例。
请注意,这些技术都不会 验证 一个电话号码,只能天真地从字符串中拉出10位数字。
最强大的解决方案是使用某种形式的专用电话号码检测器(la stuart的链接PhoneNumberFormatter)。
但是,如果您要做的是识别和提取电话号码而不必标准化数据,Apple会提供一个类NSDataDetector,可以为此配置。一个简单的例子如下所示:
NSError *error = nil;
NSDataDetector *detector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypePhoneNumber error:&error];
if(!detector) {
NSLog(@"Error creating phone number detector: %@", [error localizedDescription]);
return;
}
NSString *phoneNumberString = @"(555) 555-5555";
NSArray *matches = [detector matchesInString:phoneNumberString
options:0
range:NSMakeRange(0, [phoneNumberString length])];
if([matches count] < 1) {
NSLog(@"No phone numbers found!");
return;
}
NSTextCheckingResult *match = [matches lastObject];
if([match resultType] != NSTextCheckingTypePhoneNumber) {
NSLog(@"Matched something, but not a phone number!");
return;
}
NSString *phoneNumber = [match phoneNumber];
NSLog(@"Matched phone number: %@", phoneNumber);