Удалить все, кроме номеров из NSString - PullRequest
157 голосов
/ 15 июля 2009

У меня есть NSString (номер телефона) с некоторыми скобками и дефисами, так как некоторые номера телефонов отформатированы. Как удалить все символы, кроме цифр, из строки?

Ответы [ 22 ]

374 голосов
/ 15 сентября 2009

Старый вопрос, но как насчет:

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

Он взрывает исходную строку на множестве нецифровых чисел, а затем собирает их, используя пустой разделитель строк. Не так эффективно, как выбор символов, но гораздо более компактно в коде.

75 голосов
/ 15 июля 2009

Нет необходимости использовать библиотеку регулярных выражений, как предлагают другие ответы - класс, который вы ищете, называется 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"

РЕДАКТИРОВАТЬ: Я обновил код, потому что оригинал был написан на моей голове, и я подумал, что этого будет достаточно, чтобы указать людям правильное направление. Кажется, что люди после кода, они могут просто скопировать и вставить прямо в свое приложение.

Я также согласен с тем, что решение Майкла Пельца-Шермана более уместно, чем использование NSScanner, так что вы можете взглянуть на это.

63 голосов
/ 15 октября 2010

Принятый ответ является излишним для того, что спрашивают. Это намного проще:

NSString *pureNumbers = [[phoneNumberString componentsSeparatedByCharactersInSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet]] componentsJoinedByString:@""];
30 голосов
/ 22 июля 2009

Это здорово, но у меня не работает код на iPhone 3.0 SDK.

Если я определю strippedString, как вы видите здесь, я получаю BAD ACCESS error при попытке распечатать его после вызова 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]];
    }
}
27 голосов
/ 24 февраля 2012

Хотя это старый вопрос с рабочими ответами, я пропустил международную поддержку формата . Основанный на решении simonobo, измененный набор символов включает знак плюс "+". Международные телефонные номера также поддерживаются этой поправкой.

NSString *condensedPhoneNumber = [[phoneNumber componentsSeparatedByCharactersInSet:
              [[NSCharacterSet characterSetWithCharactersInString:@"+0123456789"]
              invertedSet]] 
              componentsJoinedByString:@""];

Выражения Swift:

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

Что дает +12345671000 в качестве общего формата международного телефонного номера.

11 голосов
/ 26 декабря 2014

Вот Swift-версия этого.

import UIKit
import Foundation
var phoneNumber = " 1 (888) 555-5551    "
var strippedPhoneNumber = "".join(phoneNumber.componentsSeparatedByCharactersInSet(NSCharacterSet.decimalDigitCharacterSet().invertedSet))
11 голосов
/ 15 июля 2015

Swift версия самого популярного ответа:

var newString = join("", oldString.componentsSeparatedByCharactersInSet(NSCharacterSet.decimalDigitCharacterSet().invertedSet))

Редактировать: Синтаксис для Swift 2

let newString = oldString.componentsSeparatedByCharactersInSet(NSCharacterSet.decimalDigitCharacterSet().invertedSet).joinWithSeparator("")

Редактировать: Синтаксис для Swift 3

let newString = oldString.components(separatedBy: CharacterSet.decimalDigits.inverted).joined(separator: "")
5 голосов
/ 24 ноября 2009

Спасибо за пример. У него есть только одна вещь, в которой отсутствует приращение scanLocation в случае, если один из символов в originalString не найден внутри объекта NumberSet. Я добавил оператор 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"
4 голосов
/ 02 декабря 2014

Принимаем только номер мобильного телефона

NSString * strippedNumber = [mobileNumber stringByReplacingOccurrencesOfString:@"[^0-9]" withString:@"" options:NSRegularExpressionSearch range:NSMakeRange(0, [mobileNumber length])];
3 голосов
/ 17 сентября 2014

Стоит отметить, что принятый ответ на основе componentsSeparatedByCharactersInSet: и componentsJoinedByString: не является эффективным с точки зрения памяти решением. Он выделяет память для набора символов, для массива и для новой строки. Даже если это только временные выделения, обработка большого количества строк таким способом может быстро заполнить память.

Подход, более дружественный к памяти, заключается в работе с изменяемой копией строки на месте. В категории над 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];
}

Профилирование двух подходов показало это, используя примерно на 2/3 меньше памяти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...