Comprimi le sequenze di spazi bianchi in un singolo carattere e una stringa di taglio


122

Considera il seguente esempio:

"    Hello      this  is a   long       string!   "

Voglio convertirlo in:

"Hello this is a long string!"

Risposte:


125

OS X 10.7+ e iOS 3.2+

Usa la soluzione regexp nativa fornita da hfossli.

Altrimenti

Utilizza la tua libreria regexp preferita o utilizza la seguente soluzione nativa di Cocoa:

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
Sarei curioso di un confronto delle prestazioni di questo con una sostituzione di regex con un taglio per rimuovere le estremità. Da un lato, hai una regex da affrontare. Dall'altro, hai un predicato. Entrambi richiedono l'elaborazione interna delle rispettive espressioni.
lilbyrdie

@lilbyrdie: Dipende dalla stringa che penso, quanti spazi bianchi ci sono. La mia soluzione è piuttosto lenta, perché crea un nuovo oggetto per ogni sottostringa e invia chiamate al metodo a ciascuna di esse.
Georg Schölly

2
Bella risposta, votata come tale, ma sfido la tua definizione di "facile". Cordiali saluti, ex ragazzo Python ora in ObjC-land ;-)
JK Laiho

2
Mi hai fatto ridere dicendo "non usare soluzioni complesse se ce n'è una facile". Quindi il più semplice è [toBeTrimmed stringByReplacingOccurrencesOfString: @ "" withString: @ ""] no? Vorrei ancora votare la tua risposta, ma è sicuramente la più semplice
Mário Carvalho

2
@ MárioCarvalho La domanda chiede come rimuovere gli spazi bianchi in eccesso , non tutti.
swilliams

52

Regex e NSCharacterSet sono qui per aiutarti. Questa soluzione taglia gli spazi bianchi iniziali e finali, nonché più spazi bianchi.

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

La registrazione final

"Hello this is a long string!"

Possibili pattern regex alternativi:

  • Sostituisci solo spazio: [ ]+
  • Sostituisci spazio e tabulazioni: [ \\t]+
  • Sostituisci spazio, tabulazioni e nuove righe: \\s+

Rundown delle prestazioni

La facilità di estensione, le prestazioni, il numero di righe di codice e il numero di oggetti creati rendono questa soluzione appropriata.


3
quella di hfossli è la risposta più elegante, nel mio libro. Inoltre ho appena imparato che puoi usare espressioni regolari in stringByReplacingOccurrencesOfString:. Non posso credere di non saperlo.
davidf2281

1
Eccezionale. Ha funzionato a
meraviglia

41

In realtà, c'è una soluzione molto semplice a questo:

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

( Fonte )


29
Penso che questo eliminerà solo gli spazi iniziali e finali e li eliminerà tutti. non si occuperà di "ciao foo"
Brian Postow

2
d * mn terminazioni di riga e formattazione automatica ... non ha a che fare con "hello______foo" (presumi _ -> "" perché la formattazione dei commenti è difficile)
Brian Postow

32
Perché votate e rispondete che non forniscono una soluzione alla domanda? stringByTrimmingCharactersInSet non analizza l'iside della stringa ma solo i bordi. La risposta di Georg Sholly è quella perfetta.
Lukasz

3
Non era esattamente una risposta alla domanda, ma sicuramente mi ha aiutato. Grazie
daveMac

1
Codice eccellente per rimuovere lo spazio iniziale e finale allo stesso tempo.
user523234

13

Con una regex, ma senza la necessità di alcun framework esterno:

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

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

Dovresti anche tagliare il risultato o verrai riempito con spazi bianchi. Questa è probabilmente la risposta più semplice, però.
lilbyrdie

2
la documentazione per NSRegularExpressionSearchdice che funziona solo con i rangeOfString:...metodi
user102008

9

Una soluzione a una riga:

NSString *whitespaceString = @" String with whitespaces ";

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

2
Mi ha aiutato :). Grazie per quello!
thedom

5
Sebbene sia utile, rimuove tutti gli spazi bianchi. L'OP vuole fondamentalmente la compattazione dello spazio bianco, ad esempio un taglio seguito dalla riduzione di uno spazio bianco consecutivo a un singolo spazio bianco.
lilbyrdie

Un'altra nota, questa soluzione non si occupa di tabulazioni o nuove righe o caratteri di spazi vuoti diversi dagli spazi.
fwielstra

2
Questo non risponde all'OP, ma rimuove invece tutti gli spazi nella stringa, così si finisce con @ "Stringwithwhitespaces"
charles

6

Questo dovrebbe farlo ...

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
Funziona effettivamente con la stringa "a"? È di lunghezza 1, per quanto posso vedere, questa soluzione filtrerà tutte le parole divise con dimensione 0 e 1.
fwielstra

Sì, questa è la risposta che mi aspettavo. Grazie +1
पवन

4

Un'altra opzione per regex è RegexKitLite , che è molto facile da incorporare in un progetto iPhone:

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

3

Prova questo

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

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

3

Ecco uno snippet da NSStringun'estensione, dove si "self"trova l' NSStringistanza. Può essere usato per comprimere gli spazi bianchi contigui in un unico spazio passando [NSCharacterSet whitespaceAndNewlineCharacterSet]e ' 'ai due argomenti.

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

Soluzione alternativa: procurati una copia di OgreKit (la libreria di espressioni regolari Cocoa).

  • OgreKit (pagina web giapponese - il codice è in inglese)
  • OgreKit (traduzione automatica di Google):

L'intera funzione è quindi:

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

Breve e dolce.

Se stai cercando la soluzione più veloce, una serie di istruzioni attentamente costruita NSScannerpotrebbe funzionare meglio, ma sarebbe necessario solo se prevedi di elaborare enormi blocchi di testo (molti megabyte).


C'è un motivo per usare OgreKit invece di RegExKitLite? regexkit.sourceforge.net Ha una chiamata a replaceOccurrencesOfRegex molto simile e funziona sulle librerie RegEX esistenti (non sono sicuro se Ogre sia un intero motore RegEX o cosa)
Kendall Helmstetter Gelner

Sono sicuro che funzioneranno entrambi. Non ho usato regexkit ma è un buon suggerimento da dare. Le persone dovrebbero scegliere in base alle librerie sottostanti: il pcre compatibile con PERL (RegExKitLite) e l'Oniguruma compatibile con Ruby (OgreKit).
Matt Gallagher

-1

secondo @Mathieu Godart è la risposta migliore, ma manca qualche riga, tutte le risposte riducono semplicemente lo spazio tra le parole, ma quando se hanno tabulazioni o hanno tab nel posto spazio, come questo: "questo è testo \ t, e \ tTab tra, così via "in tre righe di codice faremo: la stringa che vogliamo ridurre gli spazi bianchi

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

il risultato è

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

senza sostituire tab il risultato sarà:

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

-1

Puoi anche usare un semplice argomento while. Non c'è nessuna magia RegEx lì dentro, quindi forse è più facile da capire e modificare in futuro:

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

1
Non risponde alla domanda :) Non rimuove gli spazi bianchi iniziali e finali.
hfossli

-1

Le seguenti due espressioni regolari funzionerebbero a seconda dei requisiti

  1. @ "+" per la corrispondenza di spazi e tabulazioni
  2. @ "\\ s {2,}" per la corrispondenza di spazi bianchi, tabulazioni e interruzioni di riga

Quindi applica il metodo di istanza di nsstring stringByReplacingOccurrencesOfString:withString:options:range:per sostituirli con un singolo spazio bianco.

per esempio

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

Nota: non ho utilizzato la libreria "RegexKitLite" per le funzionalità di cui sopra per iOS 5.xe versioni successive.


Questa soluzione non rimuove gli spazi bianchi iniziali e finali come richiesto dall'OP.
hfossli

Gli spazi iniziali / finali @hfossli possono essere rimossi chiamando direttamente il metodo stringByTrimmingCharactersInSet: di NSString con il set di caratteri della linea nuova / bianca. La soluzione sopra era quella di rimuovere gli spazi ridondanti indipendentemente dalla loro posizione.
apalvai
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.