3

私は 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;
}
4

6 に答える 6

8

これらの回答はすべて、質問の「数字以外の文字をすべて削除する」部分には対応していません。これを行う簡単な方法は次のとおりです。

NSString *normalize(NSString *number) {
    NSMutableCharacterSet *nonNumberCharacterSet = [NSMutableCharacterSet decimalDigitCharacterSet];
    [nonNumberCharacterSet invert];

    return [[number componentsSeparatedByCharactersInSet:nonNumberCharacterSet] componentsJoinedByString:@""];
}
于 2013-03-20T06:10:32.030 に答える
0

これは、特定の目標によって異なります。

すべての入力が の形式であることが本当に確実な場合、これは、文字列からすべての空白を削除するxxx-xxx-xxxxのと同じ基本的な質問です(すでに投稿されたものと同様の回答があります)。空白を削除する代わりに、文字を削除しています. 要約: 使用(この場合は少しやり過ぎですが、以下のテクニックの代わりに使用するのに十分な場合があります)。--[NSString stringByReplacingOccurrencesOfString:withString:]-[NSString componentsSeparatedByCharactersInSet:]NSScanner

任意の形式で電話番号をサニタイズしようとしている場合、使用しているアプローチは妥当ですが、「Remove all but numbers from NSString」への回答で説明されているように、NSScanner を使用する方が少し慣用的です。また、(コードのように) 文字列を構築している場合は-appendString:-[NSString stringByAppendingString:].

ここでもrmaddy のアプローチは優れていますが、Apple の規則に従った名前を持つ NSString のカテゴリとしておそらく最も理にかなっているという警告があります。

これらの手法はいずれも電話番号を検証しないことに注意してください。単純に文字列から 10 進法で抽出するだけです。

最も堅牢な解決策は、何らかの形式の専用の電話番号検出器 (スチュアートのリンクされた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);
于 2013-03-20T06:05:59.790 に答える
0

1 つのオプションは、NSFormatter サブクラスを作成してロジックをカプセル化するか、オープン ソースのものを使用することです。PhoneNumberFormatterは有望に見え、次のようにフォーマットを削除できます。

PhoneNumberFormatter *formatter = [[PhoneNumberFormatter alloc] init];
id objectValue;
NSError *error;
[formatter getObjectValue:&objectValue forString:@"1 (234) 567-8900" errorDescription:&error];
// objectValue = @"12345678900"
于 2013-03-20T05:21:38.583 に答える