itsource

NSString에서 번호를 제외한 모든 번호 삭제

mycopycode 2023. 4. 12. 22:21
반응형

NSString에서 번호를 제외한 모든 번호 삭제

NSString(전화번호)에 괄호나 하이픈이 붙어 있는 것도 있습니다.전화번호가 포맷되어 있는 것도 있습니다.문자열에서 숫자를 제외한 모든 문자를 제거하려면 어떻게 해야 합니까?

오래된 질문이지만 다음 사항은 어떻습니까?

  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"

편집: 원문이 머릿속에서 바로 쓰여져 있어서 코드를 업데이트했습니다.그리고 그 코드만으로도 사람들을 올바른 방향으로 이끌 수 있을 것 같아서요.사람들은 코드를 찾고 있는 것 같습니다.그냥, 애플리케이션에 카피 페이스트 할 수 있습니다.

i i셔 i i셔 i i i i i는는는는는는 i i i i i i i i i i i i i i i i i를 사용하는 것보다 더 것에 동의한다.NSScanner한 번 봐주세요

받아들여진 대답은 요구되고 있는 것에 대한 과잉 살상입니다.이것은 매우 간단합니다.

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

이것은 훌륭하지만, iPhone 3.0 SDK에서는 코드가 동작하지 않습니다.

하면 stripedString이 .BAD ACCESS error하려고 할 때, 인쇄하려고 할 때scanCharactersFromSet:intoStringdiscl.discl.discl을 클릭합니다.

이렇게 하면:

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]];
    }
}

해답이 있는 해묵은 질문이지만, 국제 포맷 지원은 놓쳤습니다.시모노보의 해법에 근거해, 변경된 문자 집합은 플러스 기호 「+」를 포함한다.국제전화번호도 이 개정안에서 지원됩니다.

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 버전이 있습니다.

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))

편집: Swift 2 구문

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

편집: Swift 3 구문

let newString = oldString.components(separatedBy: CharacterSet.decimalDigits.inverted).joined(separator: "")

예시를 들어주셔서 감사합니다.숫자 CharacterSet 개체 내에 originalString 문자 중 하나가 없는 경우 scanLocation 증분이 누락된 것은 하나뿐입니다.이 문제를 해결하기 위해 다른 {} 문을 추가했습니다.

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])];

받아들인 것은 할 도 모릅니다.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 줄어든 것으로 나타났습니다.

가변 문자열에서는 정규 표현을 사용할 수 있습니다.

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:@""];

스위프트 3

let notNumberCharacters = NSCharacterSet.decimalDigits.inverted
let intString = yourString.trimmingCharacters(in: notNumberCharacters)

신속한 4.1

var str = "75003 Paris, France"
var stringWithoutDigit = (str.components(separatedBy:CharacterSet.decimalDigits)).joined(separator: "")
print(stringWithoutDigit)

첫 번째 답은 완전히 틀린 것 같아요NSS캐너는 실제로 해석하기 위한 것입니다.regex와는 달리 문자열을 한 번에 하나씩 구문 분석할 수 있습니다.스트링을 사용하여 초기화하고 스트링에 따라 취득한 거리를 나타내는 인덱스를 유지합니다.이 인덱스는 항상 참조점이 되며, 인덱스에 제공하는 명령은 해당 점을 기준으로 합니다."OK, 이 집합의 다음 문자 청크를 주세요" 또는 "문자열에서 찾을 수 있는 정수를 주세요"라고 말하면 현재 인덱스에서 시작하여 일치하지 않는 문자가 발견될 때까지 앞으로 이동합니다.첫 번째 문자가 일치하지 않으면 메서드는 NO를 반환하고 인덱스는 증가하지 않습니다.

첫 번째 예의 코드는 "(123)456-7890"에서 10진수 문자를 스캔하고 있습니다.이것은 이미 첫 번째 문자부터 실패했기 때문에 스캔 CharactersFromSet:intoString:을 스캔하는 호출은 전달된 striptedString을 그대로 두고 NO를 반환합니다.이 코드는 반환값 체크를 완전히 무시하여 strippedString Unassed로 남깁니다.첫 번째 문자가 숫자일 경우에도 첫 번째 대시나 페렌 또는 기타 어떤 것까지 발견된 숫자만 반환되므로 이 코드는 실패합니다.

꼭 NSS캐너를 사용하고 싶은 경우는, 루프에 넣어 NO의 반환치를 계속 체크할 수 있습니다.이 값을 확인했을 경우, scan Location을 증가시켜 다시 스캔 할 수 있습니다.또, isAtEnd와 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+Allow Characters(허용 문자)InSet.h

@interface NSString (AllowCharactersInSet)

- (NSString *)stringByAllowingOnlyCharactersInSet:(NSCharacterSet *)characterSet;

@end

NSString+Allow Characters(허용 문자)InSet.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

현재 최선의 방법은 다음과 같습니다.

phoneNumber.replacingOccurrences(of: "\\D",
                               with: "",
                            options: String.CompareOptions.regularExpression)

끈에서 숫자만 찾으신다면정규 표현을 사용해서 해석할 수 있을 거예요Objective-C에서 regex를 수행하는 경우 체크 아웃RegexKit. 편집: @Nathan이 지적한 바와 같이 NSS캐너를 사용하면 문자열에서 모든 번호를 구문 분석할 수 있습니다.저는 그 옵션을 전혀 몰랐기 때문에, 그것을 제안하는 것을 지지해 주세요.(저도 regex를 사용하는 것을 좋아하지 않기 때문에, 그것들을 필요로 하지 않는 어프로치를 선호합니다.)

표시하기 위해 전화번호를 포맷하고 싶다면 NSNumber를 살펴보는 것이 좋습니다.포메터이에 대한 힌트는 이 관련 SO 질문을 읽어보시기 바랍니다.전화번호는 로케이션이나 로케일에 따라 형식이 다르다는 점에 주의해 주십시오.

스위프트 5

let newString = origString.components(separatedBy: CharacterSet.decimalDigits.inverted).joined(separator: "")

Jon Vogel의 답변에 따르면 Swift String 확장과 몇 가지 기본 테스트입니다.

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 == "")
    }
}

이것은 OP의 질문에 대한 답변이지만 전화번호 관련 문자(예: ";*#+")를 남기도록 쉽게 수정할 수 있습니다.

NSString *originalPhoneNumber = @"(123) 123-456 abc";
NSCharacterSet *numbers = [[NSCharacterSet characterSetWithCharactersInString:@"0123456789"] invertedSet];
NSString *trimmedPhoneNumber = [originalPhoneNumber stringByTrimmingCharactersInSet:numbers];

];

심플하게!

언급URL : https://stackoverflow.com/questions/1129521/remove-all-but-numbers-from-nsstring

반응형