Beyaz boşluk dizilerini tek bir karaktere daraltın ve dizeyi kırpın


122

Aşağıdaki örneği düşünün:

"    Hello      this  is a   long       string!   "

Bunu şuna dönüştürmek istiyorum:

"Hello this is a long string!"

Yanıtlar:


125

OS X 10.7+ ve iOS 3.2+

Hfossli tarafından sağlanan yerel regexp çözümünü kullanın .

Aksi takdirde

En sevdiğiniz regexp kitaplığınızı kullanın veya aşağıdaki Cocoa yerel çözümü kullanın:

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

4
Bunun, uçları çıkarmak için kırpılmış bir normal ifade değişimiyle performans karşılaştırmasını merak ediyorum. Bir yandan ilgilenmeniz gereken bir normal ifadeniz var. Öte yandan, bir yükleminiz var. Ya ilgili ifadelerin dahili olarak işlenmesini gerektirir.
lilbyrdie

@lilbyrdie: Bu, düşündüğüm dizeye, kaç tane boşluk olduğuna bağlı. Çözümüm oldukça yavaş, çünkü her alt dize için yeni bir nesne yaratıyor ve her birine yöntem çağrıları gönderiyor.
Georg Schölly

2
Güzel cevap, bu şekilde oy verildi, ancak "kolay" tanımınıza meydan okuyorum. Saygılarımızla, eski Python adamı şimdi ObjC ülkesinde ;-)
JK Laiho

2
'Kolay bir çözüm varsa karmaşık çözümler kullanma' ile beni güldürdün. Yani en kolayı [toBeTrimmed stringByReplacingOccurrencesOfString: @ "" withString: @ ""] hayır mı? Hâlâ cevabınızı yükseltiyorum ama kesinlikle en kolayı
Mário Carvalho

2
@ MárioCarvalho Soru, fazla boşluğun hepsini değil, fazla boşluğun nasıl kaldırılacağını soruyor .
swilliams

52

Regex ve NSCharacterSet size yardımcı olmak için burada. Bu çözüm, baştaki ve sondaki beyaz boşluğu ve birden çok beyaz boşluğu kırpar.

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

Günlük tutma finalverir

"Hello this is a long string!"

Olası alternatif normal ifade kalıpları:

  • Yalnızca boşluğu değiştirin: [ ]+
  • Boşluğu ve sekmeleri değiştirin: [ \\t]+
  • Boşluğu, sekmeleri ve yeni satırları değiştirin: \\s+

Performans özeti

Genişletme kolaylığı, performans, kod satırı sayısı ve oluşturulan nesne sayısı bu çözümü uygun hale getirir.


3
hfossli's benim kitabımdaki en zarif cevaptır. Artı, içinde normal ifadeleri kullanabileceğinizi öğrendim stringByReplacingOccurrencesOfString:. Bunu bilmediğime inanamıyorum.
davidf2281

1
Muhteşem. Büyü gibi çalıştı
Kushal Ashok

41

Aslında bunun çok basit bir çözümü var:

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

( Kaynak )


29
Bunun sadece önde gelen ve takip eden boşlukları ortadan kaldıracağını ve hepsini ortadan kaldıracağını düşünüyorum. "merhaba foo" ile başa
çıkmayacak

2
d * mn satır sonları ve otomatik biçimlendirme ... "merhaba______foo" ile ilgilenmez (yorumları biçimlendirmek zor olduğundan _ -> "" varsayalım)
Brian Postow

32
Neden soruya çözüm getirmeyen yanıtlar veriyorsunuz? stringByTrimmingCharactersInSet, dizenin yan tarafını değil, yalnızca kenarları analiz etmez. Georg Sholly'nin cevabı mükemmel bir cevap.
Lukasz

3
Tam olarak sorunun cevabı değildi, ama kesinlikle bana yardımcı oldu. Teşekkürler
daveMac

1
Baştaki ve sondaki boşluğu aynı anda kaldırmak için mükemmel kod.
user523234

13

Bir normal ifadeyle, ancak herhangi bir dış çerçeveye ihtiyaç duymadan:

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

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

Ayrıca sonucu yine de kırpmanız gerekir, aksi takdirde boşlukla doldurulur. Yine de bu muhtemelen en basit cevaptır.
lilbyrdie

2
belgeleri, NSRegularExpressionSearchyalnızca rangeOfString:...yöntemlerle çalıştığını söylüyor
user102008

9

Tek satırlık bir çözüm:

NSString *whitespaceString = @" String with whitespaces ";

NSString *trimmedString = [whitespaceString
        stringByReplacingOccurrencesOfString:@" " withString:@""];

2
Bana yardımcı oldu :). Bunun için teşekkürler!
thedom

5
Bu yararlı olsa da, tüm boşlukları kaldırır. OP temelde beyaz boşluk sıkıştırmasını, örneğin bir kırpma ve ardından ardışık beyaz boşluğun tek bir beyaz alana indirgenmesini ister.
lilbyrdie

Başka bir not, bu çözüm, boşluklar dışında sekmeler, satırsonları veya boşluk karakterleri ile ilgilenmez.
fwielstra

2
Bu, OP'ye yanıt vermez, bunun yerine dizedeki tüm boşlukları kaldırır, böylece @ "Stringwithwhitespaces" ile sonuçlanırsınız
charles

6

Bunu yapmalı ...

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

1
Bu aslında 'a' dizesi ile çalışıyor mu? 1 uzunluğunda, görebildiğim kadarıyla, bu çözüm 0 ve 1 boyutundaki tüm bölünmüş kelimeleri filtreleyecek.
fwielstra

Evet, beklediğim cevap buydu. Teşekkürler +1
पवन

4

Regex için başka bir seçenek de, bir iPhone projesine yerleştirilmesi çok kolay olan RegexKitLite'dir :

[theString stringByReplacingOccurencesOfRegex:@" +" withString:@" "];

3

Bunu dene

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

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

3

İşte bir NSStringuzantıdan bir pasaj "self", NSStringörnek nerede . Geçen tek bir boşluğa bitişik boşluk daraltmak için kullanılabilir [NSCharacterSet whitespaceAndNewlineCharacterSet]ve ' 'iki bağımsız için.

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

-1

Alternatif çözüm: Kendinize OgreKit'in (Cocoa normal ifade kitaplığı) bir kopyasını alın.

O zaman tüm işlev:

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

Kısa ve güzel.

En hızlı çözümün peşindeyseniz, dikkatle oluşturulmuş bir dizi talimat kullanılması NSScannermuhtemelen en iyi sonucu verir, ancak bu yalnızca çok büyük (birçok megabayt) metin bloklarını işlemeyi planlıyorsanız gerekli olacaktır.


RegExKitLite yerine OgreKit kullanmak için bir neden var mı? regexkit.sourceforge.net Bu çok benzer replaceOccurrencesOfRegex görüşmesi var ve mevcut regex kütüphaneleri üstünde çalışır (değil emin Ogre bütün bir Regex motoru ya da ne ise)
Kendall Helmstetter Gelner

Eminim ikisi de çalışacaktır. Regexkit kullanmadım ama yapmak için iyi bir öneri. Kişiler temeldeki kitaplıklara göre seçim yapmalıdır: PERL uyumlu pcre (RegExKitLite) ve Ruby uyumlu Oniguruma (OgreKit).
Matt Gallagher

-1

@Mathieu Godart'a göre en iyi cevap, ancak bir satır eksik, tüm cevaplar kelimeler arasındaki boşluğu azaltır, ancak sekmeler varsa veya boşlukta sekme varsa, şöyle: "bu metin \ t ve \ tTab arasında, bu yüzden "üç satırlı kodda yapacağız: istediğimiz dize beyaz boşlukları azaltacak

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

sonuç

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

sekmeyi değiştirmeden sonuç:

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

-1

Ayrıca basit bir while argümanı da kullanabilirsiniz. Orada RegEx büyüsü yok, bu nedenle gelecekte anlamak ve değiştirmek daha kolay olabilir:

while([yourNSStringObject replaceOccurrencesOfString:@"  "
                         withString:@" "
                         options:0
                         range:NSMakeRange(0, [yourNSStringObject length])] > 0);

1
Soruya cevap vermiyor :) Baştaki ve sondaki boşlukları kaldırmaz.
hfossli

-1

İki normal ifadeyi takip etmek, gereksinimlere bağlı olarak çalışacaktır.

  1. Beyaz boşlukları ve sekmeleri eşleştirmek için @ "+"
  2. Beyaz boşlukları, sekmeleri ve satır sonlarını eşleştirmek için @ "\\ s {2,}"

Ardından, stringByReplacingOccurrencesOfString:withString:options:range:bunları tek bir beyaz boşlukla değiştirmek için nsstring'in örnek yöntemini uygulayın.

Örneğin

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

Not: iOS 5.x ve üzeri için yukarıdaki işlevsellik için 'RegexKitLite' kitaplığını kullanmadım.


Bu çözüm, OP'nin istediği gibi baştaki ve sondaki boşlukları kaldırmaz.
hfossli

@hfossli baştaki / sondaki boşluklar, NSString'in stringByTrimmingCharactersInSet: yönteminin yeni / beyaz satır karakter kümesiyle doğrudan çağrılmasıyla kaldırılabilir. Yukarıdaki çözüm, fazlalık alanları konumlarından bağımsız olarak kaldırmaktı.
apalvai
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.