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