【问题标题】:Collapse sequences of white space into a single character and trim string将空格序列折叠成单个字符并修剪字符串
【发布时间】:2010-10-19 23:34:49
【问题描述】:

考虑以下示例:

"    Hello      this  is a   long       string!   "

我想把它转换成:

"Hello this is a long string!"

【问题讨论】:

    标签: objective-c ios nsstring


    【解决方案1】:

    这是来自 NSString 扩展的 sn-p,其中 "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;
    }
    

    【讨论】:

      【解决方案2】:

      这个应该可以了……

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

      【讨论】:

      • 这真的适用于字符串'a'吗?它的长度为 1,据我所知,此解决方案将过滤掉所有大小为 0 和 1 的拆分词。
      • 是的,这就是我所期待的答案。谢谢+1
      【解决方案3】:

      替代解决方案:为自己获取一份 OgreKit(Cocoa 正则表达式库)。

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

      那么整个函数就是:

      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 引擎还是什么)
      • 我相信两者都会起作用。我没有使用过 regexkit,但它是一个很好的建议。人们应该根据底层库进行选择:PERL 兼容的 pcre (RegExKitLite) 和 Ruby 兼容的 Oniguruma (OgreKit)。
      【解决方案4】:

      正则表达式的另一个选项是RegexKitLite,它很容易嵌入到 iPhone 项目中:

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

      【讨论】:

        【解决方案5】:

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

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

        (Source)

        【讨论】:

        • 我认为这只会消除前导空格和尾随空格,并消除所有空格。它不会处理“hello foo”
        • d*mn 行结尾和自动格式化...它不处理“hello______foo”(假设 _ ->“”,因为格式化 cmets 很难)
        • 为什么你们投票和回答不能解决问题? stringByTrimmingCharactersInSet 也不分析字符串的 iside,而只分析边缘。 Georg Sholly 的回答是完美的。
        • 不完全是问题的答案,但它确实帮助了我。谢谢
        • 同时删除前导和尾随空格的优秀代码。
        【解决方案6】:

        OS X 10.7+ 和 iOS 3.2+

        使用hfossli提供的原生regexp solution

        否则

        使用您最喜欢的正则表达式库或使用以下 Cocoa-native 解决方案:

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

        【讨论】:

        • 我很好奇这与带有修剪以去除末端的正则表达式替换的性能比较。一方面,您需要处理正则表达式。另一方面,你有一个谓词。两者都需要对各自的表达式进行内部处理。
        • @lilbyrdie:这取决于我认为的字符串,有多少空格。我的解决方案很慢,因为它为每个子字符串创建一个新对象并向每个子字符串发送方法调用。
        • 很好的答案,因此被赞成,但我挑战你对“简单”的定义。此致,前 Python 人现在在 ObjC 领域 ;-)
        • 你让我发笑“如果有简单的解决方案,不要使用复杂的解决方案”。所以最简单的是 [toBeTrimmed stringByReplacingOccurrencesOfString:@" " withString:@""] 不是吗?我仍然赞成你的答案,但这绝对是最简单的
        • @MárioCarvalho 问题询问如何删除 excess 空格,而不是全部。
        【解决方案7】:

        单行解决方案:

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

        【讨论】:

        • 帮了我一把:)。谢谢!
        • 虽然这很有用,但它会删除所有空格。 OP基本上想要空格压缩,例如修剪,然后将连续空白减少为单个空白。
        • 另请注意,此解决方案不处理制表符或换行符或空格以外的空白字符。
        • 这不回答 OP,而是删除字符串中的所有空格,所以你最终得到 @"Stringwithwhitespaces"
        【解决方案8】:

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

        NSString *theString = @"    Hello      this  is a   long       string!   ";
        
        theString = [theString stringByReplacingOccurrencesOfString:@" +" withString:@" "
                               options:NSRegularExpressionSearch
                               range:NSMakeRange(0, theString.length)];
        

        【讨论】:

        • 你还需要修剪结果,否则你会被空白填充。不过,这可能是最简单的答案。
        • NSRegularExpressionSearch 的文档说它只适用于 rangeOfString:... 方法
        【解决方案9】:

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

        【讨论】:

          【解决方案10】:

          试试这个

          NSString *theString = @"    Hello      this  is a   long       string!   ";
          
          while ([theString rangeOfString:@"  "].location != NSNotFound) {
              theString = [theString stringByReplacingOccurrencesOfString:@"  " withString:@" "];
          }
          

          【讨论】:

            【解决方案11】:

            根据需求,遵循两个正则表达式会起作用

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

            然后应用 nsstring 的实例方法stringByReplacingOccurrencesOfString:withString:options:range: 将它们替换为单个空格。

            例如

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

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

            【讨论】:

            • 此解决方案不会按照 OP 的要求删除前导空格和尾随空格。
            • @hfossli 前导/尾随空格可以通过直接调用 NSString 的 stringByTrimmingCharactersInSet: 方法和新/白行字符集来删除。上述解决方案是删除与其位置无关的冗余空间。
            【解决方案12】:

            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+

            Performance rundown

            易于扩展、性能、代码行数和创建的对象数量使此解决方案非常合适。

            【讨论】:

            • 在我的书中,hfossli's 是最优雅的答案。另外,我刚刚了解到您可以在stringByReplacingOccurrencesOfString: 中使用正则表达式。不敢相信我不知道。
            • 太棒了。像魅力一样工作
            【解决方案13】:

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

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

            【讨论】:

            • 不回答问题 :) 它不会删除前导和尾随空格。
            猜你喜欢
            • 2012-03-08
            • 1970-01-01
            • 1970-01-01
            • 2015-03-16
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2022-09-27
            相关资源
            最近更新 更多