Ciutkan urutan spasi menjadi satu karakter dan potong string

122

Perhatikan contoh berikut:

"    Hello      this  is a   long       string!   "

Saya ingin mengubahnya menjadi:

"Hello this is a long string!"
hfossli.dll
sumber

Jawaban:

125

OS X 10.7+ dan iOS 3.2+

Gunakan solusi regexp asli yang disediakan oleh hfossli.

Jika tidak

Gunakan perpustakaan regexp favorit Anda atau gunakan solusi asli Kakao berikut:

NSString *theString = @"    Hello      this  is a   long       string!   ";

NSCharacterSet *whitespaces = [NSCharacterSet whitespaceCharacterSet];
NSPredicate *noEmptyStrings = [NSPredicate predicateWithFormat:@"SELF != ''"];

NSArray *parts = [theString componentsSeparatedByCharactersInSet:whitespaces];
NSArray *filteredArray = [parts filteredArrayUsingPredicate:noEmptyStrings];
theString = [filteredArray componentsJoinedByString:@" "];
Georg Schölly
sumber
4
Saya ingin tahu perbandingan kinerja ini dengan penggantian regex dengan trim untuk menghapus ujungnya. Di satu sisi, Anda memiliki ekspresi reguler yang harus ditangani. Di sisi lain, Anda memiliki predikat. Keduanya membutuhkan pemrosesan internal dari masing-masing ekspresi.
lilbyrdie
@lilbyrdie: Ini tergantung pada string yang saya pikir, ada berapa spasi putih. Solusi saya cukup lambat, karena ia membuat objek baru untuk setiap substring dan mengirimkan panggilan metode ke masing-masing substring.
Georg Schölly
2
Jawaban yang bagus, dipilih seperti itu, tapi saya menantang definisi Anda tentang "mudah". Hormat kami, mantan pria Python sekarang di ObjC-land ;-)
JK Laiho
2
Anda membuat saya tertawa dengan 'jangan gunakan solusi rumit jika ada yang mudah'. Jadi yang termudah adalah [toBeTrimmed stringByReplacingOccurrencesOfString: @ "" withString: @ ""] no? Saya masih memberikan suara positif untuk jawaban Anda, tetapi yang pasti ini yang termudah
Mário Carvalho
2
@ MárioCarvalho Pertanyaan menanyakan bagaimana cara menghapus spasi kosong berlebih , tidak semuanya.
swilliams
52

Regex dan NSCharacterSet siap membantu Anda. Solusi ini memangkas spasi putih di depan dan di belakang serta beberapa spasi putih.

NSString *original = @"    Hello      this  is a   long       string!   ";

NSString *squashed = [original stringByReplacingOccurrencesOfString:@"[ ]+"
                                                         withString:@" "
                                                            options:NSRegularExpressionSearch
                                                              range:NSMakeRange(0, original.length)];

NSString *final = [squashed stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

Penebangan finalmemberi

"Hello this is a long string!"

Pola regex alternatif yang mungkin:

  • Ganti hanya spasi: [ ]+
  • Ganti spasi dan tab: [ \\t]+
  • Ganti spasi, tab, dan baris baru: \\s+

Daftar kinerja

Kemudahan ekstensi, kinerja, jumlah baris kode dan jumlah objek yang dibuat membuat solusi ini sesuai.

hfossli.dll
sumber
3
jawaban hfossli adalah jawaban yang paling elegan, dalam buku saya. Selain itu, saya baru saja mengetahui bahwa Anda dapat menggunakan ekspresi reguler dalam stringByReplacingOccurrencesOfString:. Tidak percaya saya tidak tahu itu.
davidf2281
1
Mengagumkan. Bekerja seperti pesona
Kushal Ashok
41

Sebenarnya, ada solusi yang sangat sederhana untuk itu:

NSString *string = @" spaces in front and at the end ";
NSString *trimmedString = [string stringByTrimmingCharactersInSet:
                                  [NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSLog(@"%@", trimmedString)

( Sumber )

arikfr
sumber
29
Saya pikir ini hanya akan menghilangkan ruang depan dan belakang, dan menghilangkan semuanya. itu tidak akan berurusan dengan "hello foo"
Brian Postow
2
d * mn akhiran baris dan format otomatis ... itu tidak berhubungan dengan "hello______foo" (anggap _ -> "" karena memformat komentar itu sulit)
Brian Postow
32
Mengapa Anda orang-orang memilih dan menjawab yang tidak memberikan solusi untuk pertanyaan tersebut? stringByTrimmingCharactersInSet tidak menganalisis sisi dari string tetapi hanya tepinya. Jawaban oleh Georg Sholly adalah jawaban yang sempurna.
Lukasz
3
Sebenarnya bukan jawaban untuk pertanyaan itu, tapi pasti membantu saya. Terima kasih
daveMac
1
Kode yang sangat baik untuk menghilangkan spasi di depan dan di belakangnya pada saat yang bersamaan.
pengguna523234
13

Dengan regex, tetapi tanpa memerlukan kerangka kerja eksternal:

NSString *theString = @"    Hello      this  is a   long       string!   ";

theString = [theString stringByReplacingOccurrencesOfString:@" +" withString:@" "
                       options:NSRegularExpressionSearch
                       range:NSMakeRange(0, theString.length)];
MonsieurDart
sumber
Anda juga masih perlu memangkas hasilnya, atau Anda akan diberi spasi kosong. Ini mungkin jawaban yang paling sederhana.
lilbyrdie
2
dokumentasi untuk NSRegularExpressionSearchmengatakan bahwa itu hanya bekerja dengan rangeOfString:...metode
user102008
9

Solusi satu baris:

NSString *whitespaceString = @" String with whitespaces ";

NSString *trimmedString = [whitespaceString
        stringByReplacingOccurrencesOfString:@" " withString:@""];
TwoBeerGuy
sumber
2
Membantu saya :). Terima kasih untuk itu!
thedom
5
Meskipun ini berguna, ini menghapus semua spasi. OP pada dasarnya menginginkan pemadatan spasi, misalnya pemangkasan diikuti dengan pengurangan spasi putih berurutan menjadi satu spasi kosong.
lilbyrdie
Catatan lain, solusi ini tidak berurusan dengan tab atau baris baru atau karakter spasi selain spasi.
fwielstra
2
Ini tidak menjawab OP, tetapi menghapus semua spasi dalam string, jadi Anda berakhir dengan @ "Stringwithwhitespaces"
charles
6

Ini harus melakukannya ...

NSString *s = @"this is    a  string    with lots  of     white space";
NSArray *comps = [s componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];

NSMutableArray *words = [NSMutableArray array];
for(NSString *comp in comps) {
  if([comp length] > 1)) {
    [words addObject:comp];
  }
}

NSString *result = [words componentsJoinedByString:@" "];
Barry Wark
sumber
1
Apakah ini benar-benar berfungsi dengan string 'a'? Panjangnya 1, sejauh yang saya bisa lihat, solusi ini akan menyaring semua kata terpisah dengan ukuran 0 dan 1.
fwielstra
Ya, itulah jawaban yang saya harapkan. Terima kasih +1
पवन
4

Opsi lain untuk regex adalah RegexKitLite , yang sangat mudah disematkan dalam proyek iPhone:

[theString stringByReplacingOccurencesOfRegex:@" +" withString:@" "];
Daniel Dickison
sumber
3

Coba ini

NSString *theString = @"    Hello      this  is a   long       string!   ";

while ([theString rangeOfString:@"  "].location != NSNotFound) {
    theString = [theString stringByReplacingOccurrencesOfString:@"  " withString:@" "];
}
sinh99
sumber
3

Berikut adalah potongan dari NSStringekstensi, di mana "self"adalah NSStringcontoh. Ini dapat digunakan untuk menciutkan whitespace yang bersebelahan menjadi satu spasi dengan meneruskan [NSCharacterSet whitespaceAndNewlineCharacterSet]dan ' 'ke dua argumen.

- (NSString *) stringCollapsingCharacterSet: (NSCharacterSet *) characterSet toCharacter: (unichar) ch {
int fullLength = [self length];
int length = 0;
unichar *newString = malloc(sizeof(unichar) * (fullLength + 1));

BOOL isInCharset = NO;
for (int i = 0; i < fullLength; i++) {
    unichar thisChar = [self characterAtIndex: i];

    if ([characterSet characterIsMember: thisChar]) {
        isInCharset = YES;
    }
    else {
        if (isInCharset) {
            newString[length++] = ch;
        }

        newString[length++] = thisChar;
        isInCharset = NO;
    }
}

newString[length] = '\0';

NSString *result = [NSString stringWithCharacters: newString length: length];

free(newString);

return result;
}
dmercredi
sumber
-1

Solusi alternatif: dapatkan salinan OgreKit (pustaka ekspresi reguler Cocoa).

  • OgreKit (Halaman web Jepang - kode dalam bahasa Inggris)
  • OgreKit (terjemahan otomatis Google):

Seluruh fungsinya kemudian:

NSString *theStringTrimmed =
   [theString stringByTrimmingCharactersInSet:
        [NSCharacterSet whitespaceAndNewlineCharacterSet]];
OGRegularExpression  *regex =
    [OGRegularExpression regularExpressionWithString:@"\s+"];
return [regex replaceAllMatchesInString:theStringTrimmed withString:@" "]);

Pendek dan manis.

Jika Anda mencari solusi tercepat, serangkaian instruksi yang dibuat dengan hati-hati menggunakan NSScannermungkin akan bekerja paling baik tetapi itu hanya diperlukan jika Anda berencana untuk memproses blok teks yang besar (banyak megabyte).

Matt Gallagher
sumber
Apakah ada alasan untuk menggunakan OgreKit sebagai ganti RegExKitLite? regexkit.sourceforge.net Ini memiliki panggilan replaceOccurrencesOfRegex yang sangat mirip, dan bekerja di atas perpustakaan RegEX yang ada (tidak yakin apakah Ogre adalah mesin RegEX keseluruhan atau apa)
Kendall Helmstetter Gelner
Saya yakin keduanya akan berhasil. Saya belum pernah menggunakan regexkit tetapi ini adalah saran yang bagus untuk dibuat. Orang harus memilih berdasarkan pustaka yang mendasarinya: pcre yang kompatibel dengan PERL (RegExKitLite) dan Oniguruma yang kompatibel dengan Ruby (OgreKit).
Matt Gallagher
-1

menurut @Mathieu Godart adalah jawaban terbaik, tetapi beberapa baris hilang, semua jawaban hanya mengurangi spasi antar kata, tetapi ketika jika memiliki tab atau memiliki tab di ruang tempat, seperti ini: "ini adalah teks \ t, dan \ tTab di antara, seterusnya "dalam kode tiga baris kita akan: string yang ingin kita kurangi spasi putih

NSString * str_aLine = @"    this is text \t , and\tTab between      , so on    ";
// replace tabs to space
str_aLine = [str_aLine stringByReplacingOccurrencesOfString:@"\t" withString:@" "];
// reduce spaces to one space
str_aLine = [str_aLine stringByReplacingOccurrencesOfString:@" +" withString:@" "
                                                    options:NSRegularExpressionSearch
                                                      range:NSMakeRange(0, str_aLine.length)];
// trim begin and end from white spaces
str_aLine = [str_aLine stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

hasilnya adalah

"this is text , and Tab between , so on"

tanpa mengganti tab, hasilnya akan menjadi:

"this is text    , and  Tab between , so on"
Kosar
sumber
-1

Anda juga dapat menggunakan argumen while yang sederhana. Tidak ada keajaiban RegEx di sana, jadi mungkin lebih mudah untuk memahami dan mengubahnya di masa mendatang:

while([yourNSStringObject replaceOccurrencesOfString:@"  "
                         withString:@" "
                         options:0
                         range:NSMakeRange(0, [yourNSStringObject length])] > 0);
Sven-Steffen Arndt
sumber
1
Tidak menjawab pertanyaan :) Ini tidak menghapus spasi di depan dan di belakang.
hfossli
-1

Mengikuti dua ekspresi reguler akan berfungsi tergantung pada persyaratan

  1. @ "+" untuk mencocokkan spasi dan tab
  2. @ "\\ s {2,}" untuk mencocokkan spasi, tab, dan jeda baris

Kemudian terapkan metode instance nsstring stringByReplacingOccurrencesOfString:withString:options:range:untuk menggantinya dengan satu spasi.

misalnya

[string stringByReplacingOccurrencesOfString:regex withString:@" " options:NSRegularExpressionSearch range:NSMakeRange(0, [string length])];

Catatan: Saya tidak menggunakan pustaka 'RegexKitLite' untuk fungsionalitas di atas untuk iOS 5.x dan di atasnya.

apalvai
sumber
Solusi ini tidak menghapus spasi kosong di depan dan di belakang seperti yang diminta OP.
hfossli
@hfossli spasi di depan / belakang dapat dihapus dengan langsung memanggil metode stringByTrimmingCharactersInSet: NSString dengan kumpulan karakter baris baru / putih. Solusi di atas adalah menghapus ruang redundan yang terlepas dari lokasinya.
apalvai