Objective c 从NSString中删除除数字以外的所有内容

Objective c 从NSString中删除除数字以外的所有内容,objective-c,nsstring,Objective C,Nsstring,我有一个带有括号和连字符的NSString(电话号码),因为一些电话号码是格式化的。如何从字符串中删除除数字以外的所有字符?如果您只是想从字符串中获取数字,您当然可以使用正则表达式来解析它们。要在Objective-C中执行正则表达式,请查看编辑:正如@Nathan指出的,使用NSScanner是从字符串解析所有数字的一种更简单的方法。我完全没有意识到这个选择,所以支持他的建议。(我自己甚至不喜欢使用正则表达式,所以我更喜欢不需要它们的方法。) 如果你想格式化手机号码以便显示,值得一看。我建议你

我有一个带有括号和连字符的NSString(电话号码),因为一些电话号码是格式化的。如何从字符串中删除除数字以外的所有字符?

如果您只是想从字符串中获取数字,您当然可以使用正则表达式来解析它们。要在Objective-C中执行正则表达式,请查看编辑:正如@Nathan指出的,使用NSScanner是从字符串解析所有数字的一种更简单的方法。我完全没有意识到这个选择,所以支持他的建议。(我自己甚至不喜欢使用正则表达式,所以我更喜欢不需要它们的方法。)


如果你想格式化手机号码以便显示,值得一看。我建议你通读一下关于这样做的提示。请记住,电话号码的格式取决于位置和/或语言环境。

没有必要像其他答案所建议的那样使用正则表达式库——您要找的类称为
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"
编辑:我已经更新了代码,因为原来的代码是从我的头顶上写下来的,我想这足以让人们找到正确的方向。人们似乎在追求代码,他们可以直接复制粘贴到他们的应用程序中


我也同意Michael Pelz Sherman的解决方案比使用NSScanner更合适,所以您可能想看看。

这很好,但代码在iPhone 3.0 SDK上不适用于我

如果我如您所示定义strippedString,则在调用
scanCharactersFromSet:intoString
后尝试打印时,会出现
错误访问错误

如果我这样做:

NSMutableString *strippedString = [NSMutableString stringWithCapacity:10];
我最终得到一个空字符串,但代码没有崩溃

我不得不求助于好的老C:

for (int i=0; i<[phoneNumber length]; i++) {
    if (isdigit([phoneNumber characterAtIndex:i])) {
        [strippedString appendFormat:@"%c",[phoneNumber characterAtIndex:i]];
    }
}

用于(int i=0;iUm。第一个答案在我看来完全错了。NSScanner实际上是用于解析的。与正则表达式不同,它让你一次解析一小块字符串。你用一个字符串初始化它,它会维护一个索引,指示它沿着字符串走了多远;该索引始终是它的参考点,你给它的任何命令都是你告诉它,“好的,给我这个集合中的下一个字符块”或者“给我你在字符串中找到的整数”,这些字符从当前索引开始,然后向前移动,直到找到不匹配的字符。如果第一个字符已经不匹配,则该方法返回“否”,并且索引不会递增

第一个示例中的代码是扫描“(123)456-7890”对于已从第一个字符开始失败的十进制字符,因此对scanCharactersFromSet:intoString:的调用将只保留传入的strippedString,并返回NO;代码完全忽略检查返回值,使strippedString未赋值。即使第一个字符是数字,该代码也将失败,因为将只返回它在第一个破折号或paren或其他任何位置之前找到的数字


如果你真的想使用NSScanner,你可以将类似的东西放在一个循环中,并不断检查无返回值,如果你得到了,你可以增加扫描位置并再次扫描;你还必须检查IsAttend和yada yada yada yada。简言之,这项工作的工具是错误的。Michael的解决方案更好。

老问题,但如何布特:

  NSString *newString = [[origString componentsSeparatedByCharactersInSet:
                [[NSCharacterSet decimalDigitCharacterSet] invertedSet]] 
                componentsJoinedByString:@""];

它在一组非数字上分解源字符串,然后使用空字符串分隔符重新组合它们。效率不如在字符中拾取,但代码更紧凑。

感谢这个例子。如果找不到原始字符串中的一个字符,它只缺少扫描位置的增量在numbers CharacterSet对象中。我添加了一个else{}语句来解决这个问题

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];
  }
  // --------- Add the following to get out of endless loop
  else {
     [scanner setScanLocation:([scanner scanLocation] + 1)];
  }    
  // --------- End of addition
}

NSLog(@"%@", strippedString); // "123123123"
])


保持简单!

被接受的答案对于被问的问题来说是过分的。这要简单得多:

NSString *pureNumbers = [[phoneNumberString componentsSeparatedByCharactersInSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet]] componentsJoinedByString:@""];

虽然这是一个老问题,但我错过了国际格式支持。基于simonobo的解决方案,修改后的字符集包含一个加号“+”。国际电话号码也受此修正案的支持

NSString *condensedPhoneNumber = [[phoneNumber componentsSeparatedByCharactersInSet:
              [[NSCharacterSet characterSetWithCharactersInString:@"+0123456789"]
              invertedSet]] 
              componentsJoinedByString:@""];
快速的表达是

var phoneNumber = " +1 (234) 567-1000 "
var allowedCharactersSet = NSMutableCharacterSet.decimalDigitCharacterSet()
allowedCharactersSet.addCharactersInString("+")
var condensedPhoneNumber = phoneNumber.componentsSeparatedByCharactersInSet(allowedCharactersSet.invertedSet).joinWithSeparator("")

这将产生+12345671000作为常用的国际电话号码格式。

对于搜索电话提取的用户,您可以使用NSDataDetector从文本中提取电话号码,例如:

NSString *userBody = @"This is a text with 30612312232 my phone";
if (userBody != nil) {
    NSError *error = NULL;
    NSDataDetector *detector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypePhoneNumber error:&error];
    NSArray *matches = [detector matchesInString:userBody options:0 range:NSMakeRange(0, [userBody length])];
    if (matches != nil) {
        for (NSTextCheckingResult *match in matches) {
            if ([match resultType] == NSTextCheckingTypePhoneNumber) {
                DbgLog(@"Found phone number %@", [match phoneNumber]);
            }
        }
    }
}

`

我在NSString上创建了一个类别,以简化此常见操作

NSString+AllowCharactersInSet.h NSString+AllowCharactersInSet.m
将顶级解决方案作为一个类别构建,以帮助解决更广泛的问题:

接口:

@interface NSString (easyReplace)
- (NSString *)stringByReplacingCharactersNotInSet:(NSCharacterSet *)set 
                                             with:(NSString *)string;
@end
实施:

@implementation NSString (easyReplace)
- (NSString *)stringByReplacingCharactersNotInSet:(NSCharacterSet *)set 
                                             with:(NSString *)string
{
    NSMutableString *strippedString = [NSMutableString
                                       stringWithCapacity:self.length];

    NSScanner *scanner = [NSScanner scannerWithString:self];

    while ([scanner isAtEnd] == NO) {
        NSString *buffer;
        if ([scanner scanCharactersFromSet:set intoString:&buffer]) {
            [strippedString appendString:buffer];
        } else {
            [scanner setScanLocation:([scanner scanLocation] + 1)];
            [strippedString appendString:string];
        }
    }
    return [NSString stringWithString:strippedString];
}
@end
用法:

NSString *strippedString = 
 [originalString stringByReplacingCharactersNotInSet:
   [NSCharacterSet setWithCharactersInString:@"01234567890" 
                                        with:@""];

您可以在可变字符串上使用正则表达式:

NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:
                                @"[^\\d]"
                                options:0
                                error:nil];

[regex replaceMatchesInString:str
                      options:0 
                        range:NSMakeRange(0, str.length) 
                 withTemplate:@""];

可能值得注意的是,基于
组件separatedbycharactersinset:
组件joinedbystring:
的答案并不是一个节省内存的解决方案。它为字符集、数组和新字符串分配内存。即使这些只是临时分配,也会以这种方式处理大量字符串能很快填满记忆

内存友好的方法是在字符串的可变副本上操作。在NSString上的类别中:

-(NSString *)stringWithNonDigitsRemoved {
    static NSCharacterSet *decimalDigits;
    if (!decimalDigits) {
        decimalDigits = [NSCharacterSet decimalDigitCharacterSet];
    }
    NSMutableString *stringWithNonDigitsRemoved = [self mutableCopy];
    for (CFIndex index = 0; index < stringWithNonDigitsRemoved.length; ++index) {
        unichar c = [stringWithNonDigitsRemoved characterAtIndex: index];
        if (![decimalDigits characterIsMember: c]) {
            [stringWithNonDigitsRemoved deleteCharactersInRange: NSMakeRange(index, 1)];
            index -= 1;
        }
    }
    return [stringWithNonDigitsRemoved copy];
}
-(NSString*)stringWithNonDigitsRemoved{
静态NSCharacterSet*小数位数;
如果(!小数位数){
小数位数=[NSCharacterSet decimalDigitCharacterSet];
}
NSMutableString*stringWithNonDigitsRemoved=[self-mutableCopy];
对于(CFIndex index=0;indexNSString *strippedString = 
 [originalString stringByReplacingCharactersNotInSet:
   [NSCharacterSet setWithCharactersInString:@"01234567890" 
                                        with:@""];
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:
                                @"[^\\d]"
                                options:0
                                error:nil];

[regex replaceMatchesInString:str
                      options:0 
                        range:NSMakeRange(0, str.length) 
                 withTemplate:@""];
-(NSString *)stringWithNonDigitsRemoved {
    static NSCharacterSet *decimalDigits;
    if (!decimalDigits) {
        decimalDigits = [NSCharacterSet decimalDigitCharacterSet];
    }
    NSMutableString *stringWithNonDigitsRemoved = [self mutableCopy];
    for (CFIndex index = 0; index < stringWithNonDigitsRemoved.length; ++index) {
        unichar c = [stringWithNonDigitsRemoved characterAtIndex: index];
        if (![decimalDigits characterIsMember: c]) {
            [stringWithNonDigitsRemoved deleteCharactersInRange: NSMakeRange(index, 1)];
            index -= 1;
        }
    }
    return [stringWithNonDigitsRemoved copy];
}
NSString * strippedNumber = [mobileNumber stringByReplacingOccurrencesOfString:@"[^0-9]" withString:@"" options:NSRegularExpressionSearch range:NSMakeRange(0, [mobileNumber length])];
import UIKit
import Foundation
var phoneNumber = " 1 (888) 555-5551    "
var strippedPhoneNumber = "".join(phoneNumber.componentsSeparatedByCharactersInSet(NSCharacterSet.decimalDigitCharacterSet().invertedSet))
var newString = join("", oldString.componentsSeparatedByCharactersInSet(NSCharacterSet.decimalDigitCharacterSet().invertedSet))
let newString = oldString.componentsSeparatedByCharactersInSet(NSCharacterSet.decimalDigitCharacterSet().invertedSet).joinWithSeparator("")
let newString = oldString.components(separatedBy: CharacterSet.decimalDigits.inverted).joined(separator: "")
import Foundation
extension String {
    func stringByRemovingNonNumericCharacters() -> String {
        return self.componentsSeparatedByCharactersInSet(NSCharacterSet.decimalDigitCharacterSet().invertedSet).joinWithSeparator("")
    }
}
import XCTest

class StringExtensionTests: XCTestCase {

    func testStringByRemovingNonNumericCharacters() {

        let baseString = "123"
        var testString = baseString
        var newString = testString.stringByRemovingNonNumericCharacters()
        XCTAssertTrue(newString == testString)

        testString = "a123b"
        newString = testString.stringByRemovingNonNumericCharacters()
        XCTAssertTrue(newString == baseString)

        testString = "a=1-2_3@b"
        newString = testString.stringByRemovingNonNumericCharacters()
        XCTAssertTrue(newString == baseString)

        testString = "(999) 999-9999"
        newString = testString.stringByRemovingNonNumericCharacters()
        XCTAssertTrue(newString.characters.count == 10)
        XCTAssertTrue(newString == "9999999999")

        testString = "abc"
        newString = testString.stringByRemovingNonNumericCharacters()
        XCTAssertTrue(newString == "")
    }
}
let notNumberCharacters = NSCharacterSet.decimalDigits.inverted
let intString = yourString.trimmingCharacters(in: notNumberCharacters)
phoneNumber.replacingOccurrences(of: "\\D",
                               with: "",
                            options: String.CompareOptions.regularExpression)
var str = "75003 Paris, France"
var stringWithoutDigit = (str.components(separatedBy:CharacterSet.decimalDigits)).joined(separator: "")
print(stringWithoutDigit)
let newString = origString.components(separatedBy: CharacterSet.decimalDigits.inverted).joined(separator: "")