将空白序列折叠为单个字符和修剪字符串


122

考虑以下示例:

"    Hello      this  is a   long       string!   "

我想将其转换为:

"Hello this is a long string!"

Answers:


125

OS X 10.7+和iOS 3.2+

使用hfossli提供的本机regexp解决方案

除此以外

使用您喜欢的正则表达式库或使用以下可可本地解决方案:

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
我很好奇这一性能与正则表达式替代品的性能比较,正则表达式替代品带有修边以去除末端。一方面,您需要处理正则表达式。另一方面,您有一个谓词。两者都需要内部处理各个表达式。
lilbyrdie 2011年

@lilbyrdie:这取决于我认为的字符串,有多少个空格。我的解决方案很慢,因为它为每个子字符串创建一个新对象,并将方法调用发送给每个子字符串。
GeorgSchölly

2
好的回答,被这样支持,但我对您对“简单”的定义提出质疑。真诚的是,以前的Python家伙现在在ObjC-land ;-)
JK Laiho

2
您以“如果有简单的解决方案就不要使用复杂的解决方案”使我发笑。因此,最简单的方法是[toBeTrimmed stringByReplacingOccurrencesOfString:@“” withString:@“”]不?我还给予好评的答案,但它绝对是最简单的
马里奥·卡瓦略

2
@MárioCarvalho该问题询问如何删除多余的空格,而不是全部。
2013年

52

正则表达式和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
在我的书中,hfossli的答案是最优雅的。另外,我刚刚了解到您可以在中使用正则表达式stringByReplacingOccurrencesOfString:。不敢相信我不知道。
davidf2281

1
太棒了 像魅力一样
运作

41

实际上,有一个非常简单的解决方案:

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

来源


29
我认为这将仅消除前导和尾随空格,并消除所有空格。它不会处理“ hello foo”
Brian Postow 09年

2
d * mn行结尾和自动格式化...它不处理“ hello ______ foo”(假设_->“”因为格式化注释很困难)
Brian Postow 09年

32
你们为什么投票和回答却无法解决问题?stringByTrimmingCharactersInSet也不分析字符串的iside,仅分析边缘。Georg Sholly的回答是完美的选择。
卢卡斯,

3
不能完全回答这个问题,但确实可以帮助我。谢谢
daveMac

1
出色的代码,可同时删除前导空间和尾随空间。
user523234

13

使用正则表达式,但不需要任何外部框架:

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

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

然后,您仍然需要修剪结果,否则将被空白填充。不过,这可能是最简单的答案。
lilbyrdie 2011年

2
的文档NSRegularExpressionSearch说,它仅适用于以下rangeOfString:...方法
user102008 2011年

9

一线解决方案:

NSString *whitespaceString = @" String with whitespaces ";

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

2
帮助我了:)。感谢那!
thedom

5
尽管这很有用,但它会删除所有空白。OP基本上希望进行空格压缩,例如修剪,然后将连续的空格减少为单个空格。
lilbyrdie 2011年

请注意,此解决方案不处理制表符,换行符或空格字符(空格除外)。
fwielstra '02

2
这不会回答OP,而是删除字符串中的所有空格,所以您最终得到@“ Stringwithwhitespaces”
charles

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

1
这实际上适用于字符串“ a”吗?它的长度为1的,据我所看到的,这种解决方案将筛选出大小为0和1的所有分割的话
fwielstra

是的,这就是我期望的答案。感谢+1
2012年


3

试试这个

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

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

3

下面是一个片段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;
}

-1

替代解决方案:为自己获取OgreKit(可可正则表达式库)的副本。

  • OgreKit(日语网页-代码为英文)
  • OgreKit(Google自动翻译):

整个函数如下:

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

简短而甜美。

如果您追求最快的解决方案,那么精心设计的一系列使用说明NSScanner可能会效果最好,但这仅在您计划处理巨大(许多兆字节)的文本块时才需要。


是否有理由使用OgreKit而不是RegExKitLite? regexkit.sourceforge.net 它具有非常相似的replaceOccurrencesOfRegex调用,并且可以在现有RegEX库之上运行(不确定Ogre是否是一个完整的RegEX引擎或其他)
Kendall Helmstetter Gelner 2009年

我相信两者都可以。我没有使用过regexkit,但是它是一个很好的建议。人们应该基于以下基础库进行选择:兼容PERL的pcre(RegExKitLite)和兼容Ruby的Oniguruma(OgreKit)。
Matt Gallagher

-1

@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"

在不替换选项卡的情况下,结果将为:

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

-1

您也可以使用简单的while参数。那里没有RegEx魔术,所以也许将来更容易理解和更改:

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

1
不回答问题:)它不会删除开头和结尾的空格。
hfossli 2014年

-1

根据要求,以下两个正则表达式将起作用

  1. @“ +”用于匹配空格和制表符
  2. @“ \\ s {2,}”用于匹配空格,制表符和换行符

然后应用nsstring的instance方法stringByReplacingOccurrencesOfString:withString:options:range:将其替换为单个空格。

例如

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

注意:对于iOS 5.x及更高版本,我没有为上述功能使用'RegexKitLite'库。


此解决方案不会按照OP的要求删除前导和尾随空格。
hfossli 2014年

@hfossli的前导/尾随空格可以通过直接调用带有新行/白线字符集的NSString的stringByTrimmingCharactersInSet:方法来删除。上面的解决方案是删除与位置无关的冗余空间。
apalvai 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.