Saya memiliki NSString (nomor telepon) dengan beberapa tanda kurung dan tanda hubung karena beberapa nomor telepon diformat. Bagaimana saya menghapus semua karakter kecuali angka dari string?
Saya memiliki NSString (nomor telepon) dengan beberapa tanda kurung dan tanda hubung karena beberapa nomor telepon diformat. Bagaimana saya menghapus semua karakter kecuali angka dari string?
Jawaban:
Pertanyaan lama, tapi bagaimana dengan:
NSString *newString = [[origString componentsSeparatedByCharactersInSet:
[[NSCharacterSet decimalDigitCharacterSet] invertedSet]]
componentsJoinedByString:@""];
Ini meledak string sumber pada set non-digit, lalu pasang kembali menggunakan pemisah string kosong. Tidak seefisien memilih karakter, tetapi jauh lebih ringkas dalam kode.
NSString *pureNumbers = [pureNumbers stringByTrimmingCharactersInSet: [NSCharacterSet decimalDigitCharacterSet] invertedSet]
tidak bekerja?
[NSCharacterSet decimalDigitCharacterSet]
dengan yang lain yang hanya berisi angka dan huruf. Anda dapat membangunnya dengan membuat a NSMutableCharaterSet
dan meneruskan a decimalDigitCharacterSet
, uppercaseLetterCharacterSet
dan lowercaseLetterCharacterSet
ke formUnionWithCharacterSet:
. Catatan yang letterCharacterSet
menyertakan tanda juga, maka penggunaan versi huruf kecil dan besar.
Tidak perlu menggunakan pustaka ekspresi reguler seperti jawaban yang disarankan - kelas yang Anda cari dipanggil NSScanner
. Ini digunakan sebagai berikut:
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"
EDIT: Saya telah memperbarui kode karena yang asli dihapus dari atas kepala saya dan saya pikir itu akan cukup untuk mengarahkan orang ke arah yang benar. Tampaknya orang-orang mengejar kode mereka hanya dapat menyalin-menempel langsung ke aplikasi mereka.
Saya juga setuju bahwa solusi Michael Pelz-Sherman lebih tepat daripada menggunakan NSScanner
, jadi Anda mungkin ingin melihatnya.
Jawaban yang diterima terlalu banyak untuk apa yang diminta. Ini jauh lebih sederhana:
NSString *pureNumbers = [[phoneNumberString componentsSeparatedByCharactersInSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet]] componentsJoinedByString:@""];
Ini bagus, tetapi kodenya tidak berfungsi untuk saya di iPhone 3.0 SDK.
Jika saya mendefinisikan strippedString seperti yang Anda tunjukkan di sini, saya mendapatkan BAD ACCESS error
ketika mencoba mencetaknya setelah scanCharactersFromSet:intoString
panggilan.
Jika saya melakukannya seperti itu:
NSMutableString *strippedString = [NSMutableString stringWithCapacity:10];
Saya berakhir dengan string kosong, tetapi kode tidak macet.
Saya harus menggunakan C lama yang baik sebagai gantinya:
for (int i=0; i<[phoneNumber length]; i++) {
if (isdigit([phoneNumber characterAtIndex:i])) {
[strippedString appendFormat:@"%c",[phoneNumber characterAtIndex:i]];
}
}
Meskipun ini adalah pertanyaan lama dengan jawaban yang berfungsi, saya kehilangan dukungan format internasional . Berdasarkan solusi simonobo, set karakter yang diubah mencakup tanda tambah "+". Nomor telepon internasional juga didukung oleh amandemen ini.
NSString *condensedPhoneNumber = [[phoneNumber componentsSeparatedByCharactersInSet:
[[NSCharacterSet characterSetWithCharactersInString:@"+0123456789"]
invertedSet]]
componentsJoinedByString:@""];
Ekspresi Swift adalah
var phoneNumber = " +1 (234) 567-1000 "
var allowedCharactersSet = NSMutableCharacterSet.decimalDigitCharacterSet()
allowedCharactersSet.addCharactersInString("+")
var condensedPhoneNumber = phoneNumber.componentsSeparatedByCharactersInSet(allowedCharactersSet.invertedSet).joinWithSeparator("")
Yang menghasilkan +12345671000 sebagai format nomor telepon internasional umum.
Ini adalah versi Swift dari ini.
import UIKit
import Foundation
var phoneNumber = " 1 (888) 555-5551 "
var strippedPhoneNumber = "".join(phoneNumber.componentsSeparatedByCharactersInSet(NSCharacterSet.decimalDigitCharacterSet().invertedSet))
Versi cepat dari jawaban paling populer:
var newString = join("", oldString.componentsSeparatedByCharactersInSet(NSCharacterSet.decimalDigitCharacterSet().invertedSet))
Sunting: Sintaks untuk Swift 2
let newString = oldString.componentsSeparatedByCharactersInSet(NSCharacterSet.decimalDigitCharacterSet().invertedSet).joinWithSeparator("")
Sunting: Sintaks untuk Swift 3
let newString = oldString.components(separatedBy: CharacterSet.decimalDigits.inverted).joined(separator: "")
Terima kasih untuk contohnya. Itu hanya memiliki satu hal yang hilang penambahan scanLocation jika salah satu karakter dalam originalString tidak ditemukan di dalam objek nomor CharacterSet. Saya telah menambahkan pernyataan lain {} untuk memperbaikinya.
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"
Mungkin perlu dicatat bahwa jawaban yang diterima componentsSeparatedByCharactersInSet:
dan componentsJoinedByString:
berbasis bukan solusi yang efisien memori. Ini mengalokasikan memori untuk set karakter, untuk array dan untuk string baru. Bahkan jika ini hanya alokasi sementara, memproses banyak string dengan cara ini dapat dengan cepat mengisi memori.
Sebuah pendekatan yang lebih ramah memori adalah untuk beroperasi pada salinan string yang dapat berubah di tempatnya. Dalam kategori di atas 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];
}
Profil kedua pendekatan telah menunjukkan ini menggunakan sekitar 2/3 lebih sedikit memori.
Membangun solusi teratas sebagai kategori untuk membantu masalah yang lebih luas:
Antarmuka:
@interface NSString (easyReplace)
- (NSString *)stringByReplacingCharactersNotInSet:(NSCharacterSet *)set
with:(NSString *)string;
@end
Implemenasi:
@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
Pemakaian:
NSString *strippedString =
[originalString stringByReplacingCharactersNotInSet:
[NSCharacterSet setWithCharactersInString:@"01234567890"
with:@""];
cepat 4.1
var str = "75003 Paris, France"
var stringWithoutDigit = (str.components(separatedBy:CharacterSet.decimalDigits)).joined(separator: "")
print(stringWithoutDigit)
Um Jawaban pertama tampaknya sama sekali salah bagi saya. NSScanner benar-benar dimaksudkan untuk parsing. Tidak seperti regex, ini membuat Anda mengurai string satu potongan kecil sekaligus. Anda menginisialisasi dengan string, dan mempertahankan indeks seberapa jauh sepanjang string itu didapat; Indeks itu selalu menjadi titik rujukannya, dan perintah apa pun yang Anda berikan relatif terhadap titik itu. Anda mengatakannya, "ok, beri saya potongan karakter berikutnya dalam set ini" atau "beri saya bilangan bulat yang Anda temukan dalam string", dan mereka mulai pada indeks saat ini, dan bergerak maju sampai mereka menemukan sesuatu yang tidak pertandingan. Jika karakter pertama sudah tidak cocok, maka metode mengembalikan NO, dan indeks tidak bertambah.
Kode dalam contoh pertama adalah pemindaian "(123) 456-7890" untuk karakter desimal, yang sudah gagal dari karakter pertama, sehingga panggilan untuk memindaiCharactersFromSet: keString: membiarkan strippedString yang dilewati saja, dan mengembalikan TIDAK; Kode benar-benar mengabaikan memeriksa nilai kembali, meninggalkan strippedString tidak ditetapkan. Bahkan jika karakter pertama adalah digit, kode itu akan gagal, karena hanya akan mengembalikan digit yang ditemukannya hingga tanda hubung pertama atau paren atau apa pun.
Jika Anda benar-benar ingin menggunakan NSScanner, Anda dapat memasukkan sesuatu seperti itu dalam satu lingkaran, dan terus memeriksa nilai pengembalian NO, dan jika Anda mendapatkannya Anda dapat menambahkan scanLocation dan memindai lagi; dan Anda juga harus memeriksa isAtEnd, dan yada yada yada. Singkatnya, alat yang salah untuk pekerjaan itu. Solusi Michael lebih baik.
Untuk mereka yang mencari ekstraksi telepon, Anda dapat mengekstrak nomor telepon dari teks menggunakan NSDataDetector, misalnya:
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]);
}
}
}
}
`
Saya membuat kategori pada NSString untuk menyederhanakan operasi umum ini.
@interface NSString (AllowCharactersInSet)
- (NSString *)stringByAllowingOnlyCharactersInSet:(NSCharacterSet *)characterSet;
@end
@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
Jika Anda hanya ingin mengambil angka dari string, Anda tentu bisa menggunakan ekspresi reguler untuk menguraikannya. Untuk melakukan regex di Objective-C, periksa RegexKit . Sunting: Seperti yang ditunjukkan Nathan, menggunakan NSScanner adalah cara yang lebih sederhana untuk mem-parsing semua angka dari sebuah string. Saya benar-benar tidak menyadari pilihan itu, jadi dia menyarankan untuk menyarankannya. (Saya bahkan tidak suka menggunakan regex sendiri, jadi saya lebih suka pendekatan yang tidak memerlukannya.)
Jika Anda ingin memformat nomor telepon untuk tampilan, ada baiknya melihat NSNumberFormatter . Saya sarankan Anda membaca pertanyaan SO terkait ini untuk tips tentang melakukannya. Ingat bahwa nomor telepon diformat berbeda tergantung pada lokasi dan / atau lokal.
Cepat 5
let newString = origString.components(separatedBy: CharacterSet.decimalDigits.inverted).joined(separator: "")
Berdasarkan jawaban Jon Vogel di sini itu adalah sebagai ekstensi Swift String bersama dengan beberapa tes dasar.
import Foundation
extension String {
func stringByRemovingNonNumericCharacters() -> String {
return self.componentsSeparatedByCharactersInSet(NSCharacterSet.decimalDigitCharacterSet().invertedSet).joinWithSeparator("")
}
}
Dan beberapa tes membuktikan setidaknya fungsi dasar:
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 == "")
}
}
Ini menjawab pertanyaan OP tetapi bisa dengan mudah dimodifikasi untuk meninggalkan karakter terkait nomor telepon seperti ",; * # +"
NSString *originalPhoneNumber = @"(123) 123-456 abc";
NSCharacterSet *numbers = [[NSCharacterSet characterSetWithCharactersInString:@"0123456789"] invertedSet];
NSString *trimmedPhoneNumber = [originalPhoneNumber stringByTrimmingCharactersInSet:numbers];
];
Tetap sederhana!
NSCharacterSet *myCharSet = [NSCharacterSet characterSetWithCharactersInString:@"charactersGoHere"]