一部の電話番号がフォーマットされているため、括弧とハイフンを含む NSString (電話番号) があります。文字列から数字以外のすべての文字を削除するにはどうすればよいですか?
22 に答える
古い質問ですが、どうですか:
NSString *newString = [[origString componentsSeparatedByCharactersInSet:
[[NSCharacterSet decimalDigitCharacterSet] invertedSet]]
componentsJoinedByString:@""];
数字以外のセットでソース文字列を分解し、空の文字列セパレータを使用してそれらを再構成します。文字を選択するほど効率的ではありませんが、コードははるかにコンパクトです。
他の回答が示唆しているように、正規表現ライブラリを使用する必要はありません-あなたが求めているクラスはと呼ばれ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
ます。そのため、それを確認することをお勧めします。
受け入れられた答えは、求められていることに対してやり過ぎです。これははるかに簡単です:
NSString *pureNumbers = [[phoneNumberString componentsSeparatedByCharactersInSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet]] componentsJoinedByString:@""];
これはすばらしいことですが、iPhone 3.0 SDK ではコードが機能しません。
ここに示すように strippedString を定義するBAD ACCESS error
と、呼び出し後にそれを印刷しようとしたときに a が表示されます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]];
}
}
これは実用的な答えのある古い質問ですが、国際フォーマットのサポートを逃しました。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が生成されます。
最も人気のある回答の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: "")
例をありがとう。originalString の文字の 1 つが数値の CharacterSet オブジェクト内に見つからない場合に備えて、scanLocation のインクリメントが欠落しているものは 1 つだけです。これを修正するために、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 * strippedNumber = [mobileNumber stringByReplacingOccurrencesOfString:@"[^0-9]" withString:@"" options:NSRegularExpressionSearch range:NSMakeRange(0, [mobileNumber length])];
変更可能な文字列で正規表現を使用できます。
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:
@"[^\\d]"
options:0
error:nil];
[regex replaceMatchesInString:str
options:0
range:NSMakeRange(0, str.length)
withTemplate:@""];
より広範な問題に役立つカテゴリとしてトップ ソリューションを構築しました。
インターフェース:
@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:@""];
うーん。最初の答えは私には完全に間違っているようです。NSScanner は、実際には解析を目的としています。正規表現とは異なり、一度に 1 つの小さなチャンクの文字列を解析する必要があります。文字列で初期化すると、取得した文字列に沿った距離のインデックスが維持されます。そのインデックスは常にその基準点であり、与えられたコマンドはその点に関連しています。「わかりました、このセットの次の文字のチャンクをください」または「文字列で見つけた整数を教えてください」と言うと、それらは現在のインデックスから始まり、そうでないものが見つかるまで先に進みますマッチ。最初の文字がまだ一致していない場合、メソッドは NO を返し、インデックスは増加しません。
最初の例のコードは、10 進文字の "(123)456-7890" をスキャンしていますが、これは最初の文字からすでに失敗しています。コードは戻り値のチェックを完全に無視し、strippedString を未割り当てのままにしています。最初の文字が数字だったとしても、そのコードは失敗します。最初のダッシュや括弧などまで見つかった数字しか返さないからです。
本当に NSScanner を使用したい場合は、そのようなものをループに入れ、NO の戻り値をチェックし続けます。それが得られた場合は、scanLocation をインクリメントして再度スキャンすることができます。isAtEnd と yada yada yada もチェックする必要があります。要するに、仕事のための間違ったツールです。マイケルのソリューションの方が優れています。
電話番号抽出を検索する場合は、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
@interface NSString (AllowCharactersInSet)
- (NSString *)stringByAllowingOnlyCharactersInSet:(NSCharacterSet *)characterSet;
@end
NSString+AllowCharactersInSet.m
@implementation NSString (AllowCharactersInSet)
- (NSString *)stringByAllowingOnlyCharactersInSet:(NSCharacterSet *)characterSet {
NSMutableString *strippedString = [NSMutableString
stringWithCapacity:self.length];
NSScanner *scanner = [NSScanner scannerWithString:self];
while (!scanner.isAtEnd) {
NSString *buffer = nil;
if ([scanner scanCharactersFromSet:characterSet intoString:&buffer]) {
[strippedString appendString:buffer];
} else {
scanner.scanLocation = scanner.scanLocation + 1;
}
}
return strippedString;
}
@end
文字列から数値を取得するだけの場合は、正規表現を使用してそれらを解析できます。Objective-C で正規表現を行うには、RegexKitを確認してください。 編集: @Nathan が指摘するように、NSScanner を使用すると、文字列からすべての数値を解析するより簡単な方法になります。私はそのオプションをまったく知らなかったので、それを提案してくれた彼に感謝します. (私自身も正規表現を使用するのは好きではないので、正規表現を必要としないアプローチを好みます。)
表示用に電話番号をフォーマットしたい場合は、NSNumberFormatterを見てみる価値があります。そのためのヒントについては、この関連する SO の質問を読むことをお勧めします。電話番号の形式は、場所やロケールによって異なることに注意してください。
NSString *originalPhoneNumber = @"(123) 123-456 abc";
NSCharacterSet *numbers = [[NSCharacterSet characterSetWithCharactersInString:@"0123456789"] invertedSet];
NSString *trimmedPhoneNumber = [originalPhoneNumber stringByTrimmingCharactersInSet:numbers];
];
複雑にしないでおく!