Свернуть последовательности белого пробела в один символ и обрезать строку

Рассмотрим следующий пример:

"    Hello      this  is a   long       string!   "

Я хочу преобразовать это:

"Hello this is a long string!"

Ответ 1

OS X 10.7+ и iOS 3.2 +

Используйте встроенное regexp решение, предоставленное hfossli.

В противном случае

Используйте либо свою любимую библиотеку регулярных выражений, либо используйте следующее 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:@" "];

Ответ 2

Regex и NSCharacterSet здесь, чтобы помочь вам. Это решение обрезает ведущие и конечные пробелы, а также несколько пробелов.

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

Запись final дает

"Hello this is a long string!"

Возможные альтернативные шаблоны регулярных выражений:

  • Заменить только пространство: [ ]+
  • Заменить пространство и вкладки: [ \\t]+
  • Заменить пространство, вкладки и символы новой строки: \\s+

Снижение производительности

Простота расширения, производительности, числовых строк кода и количества созданных объектов делает это решение подходящим.

Ответ 3

На самом деле существует очень простое решение:

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

(Источник)

Ответ 4

С регулярным выражением, но без необходимости в любой внешней структуре:

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

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

Ответ 5

Однострочное решение:

NSString *whitespaceString = @" String with whitespaces ";

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

Ответ 6

Это должно сделать это...

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

Ответ 7

Другим вариантом для regex является RegexKitLite, который очень легко внедрить в проект iPhone:

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

Ответ 8

Здесь фрагмент из расширения NSString, где "self" является экземпляром NSString. Его можно использовать для сглаживания смежных пробелов в одно пространство путем передачи в [NSCharacterSet whitespaceAndNewlineCharacterSet] и ' ' двух аргументов.

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

Ответ 9

Попробуйте это

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

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

Ответ 10

Альтернативное решение: получите копию OgreKit (библиотека регулярных выражений Cocoa).

  • OgreKit (японская страница - код на английском языке)
  • OgreKit (Google автоперевод):

Вся функция тогда:

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

Короткий и сладкий.

Если вы выполняете самое быстрое решение, тщательно разработанная серия инструкций с использованием NSScanner, вероятно, будет работать лучше всего, но это будет необходимо, только если вы планируете обрабатывать огромные (много мегабайт) блоки текста.

Ответ 11

в соответствии с @Mathieu Godart - лучший ответ, но какая-то строка отсутствует, все ответы просто уменьшают пробел между словами, но если у вас есть вкладки или есть вкладка в место, например: "это текст \t, и\tTab между, и так далее", в трех строках мы будем: строка, которую мы хотим уменьшить пробелы

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

результат

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

без замены вкладки resul будет:

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

Ответ 12

Следующие два регулярных выражения будут работать в зависимости от требований

  • @ "+" для сопоставления пробелов и вкладок
  • @ "\\ s {2,}" для сопоставления пробелов, вкладок и разрывов строк

Затем примените метод экземпляра nsstring stringByReplacingOccurrencesOfString:withString:options:range:, чтобы заменить их одним пробелом.

например.

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

Примечание. Я не использовал библиотеку RegexKitLite для вышеупомянутых функций для iOS 5.x и выше.

Ответ 13

Вы также можете использовать простой аргумент while. Там нет волшебства RegEx, поэтому, возможно, его легче понять и изменить в будущем:

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