【问题标题】:How do I convert an NSString from CamelCase to TitleCase, 'playerName' into 'Player Name'?如何将 NSString 从 CamelCase 转换为 TitleCase,将“playerName”转换为“Player Name”?
【发布时间】:2011-06-03 03:31:08
【问题描述】:

我正在寻找将字符串从驼峰格式转换为标题大小写格式的最简单方法。

如何将“playerName”更改为“Player Name”?

【问题讨论】:

  • 用什么语言? (难道 cocoa 不是一种 API 而不是一种语言吗?)字符串是非常特定于语言的。

标签: objective-c string cocoa camelcasing


【解决方案1】:
NSString *str = @"playerName";
NSMutableString *str2 = [NSMutableString string];

for (NSInteger i=0; i<str.length; i++){
    NSString *ch = [str substringWithRange:NSMakeRange(i, 1)];
    if ([ch rangeOfCharacterFromSet:[NSCharacterSet uppercaseLetterCharacterSet]].location != NSNotFound) {
        [str2 appendString:@" "];
    }
    [str2 appendString:ch];
}
NSLog(@"%@", str2.capitalizedString);

【讨论】:

  • 干得好!是的,这肯定更短!我在这里传递了接受的答案,除非其他人可以找到更短的方法来做到这一点。
  • 我认为还有更短的方法可以做到这一点......对于这样一个简单的任务来说,其他的方法太长了:/
  • 这个解决方案根本不处理表情符号,如果第一个字符是大写,它会在第一个字符之前插入一个空格。
  • @orj 只需将字符集从 [NSCharacterSet uppercaseLetterCharacterSet] 更改为您根据需要派生的字符集
【解决方案2】:

这是一个更简单的 Swift 版本。我已将其放入扩展程序中

extension String {

    func stringFromCamelCase() -> String {
        var string = self
        string = string.stringByReplacingOccurrencesOfString("([a-z])([A-Z])", withString: "$1 $2", options: NSStringCompareOptions.RegularExpressionSearch, range: Range<String.Index>(start: string.startIndex, end: string.endIndex))
        string.replaceRange(startIndex...startIndex, with: String(self[startIndex]).capitalizedString)
        return string
    }

}

用法:

var str = "helloWorld"
str = str.stringFromCamelCase()

【讨论】:

  • 已针对 Swift 3 更新,可以简化为 return self.replacingOccurrences(of: "([a-z])([A-Z])", with: "$1 $2", options: .regularExpression, range: self.startIndex ..&lt; self.endIndex).capitalized
【解决方案3】:

尝试使用正则表达式替换

NSString *modified = [input stringByReplacingOccurrencesOfString:@"([a-z])([A-Z])"
                                                      withString:@"$1 $2"
                                                         options:NSRegularExpressionSearch
                                                           range:NSMakeRange(0, input.length)];

【讨论】:

  • 哇!一条线!注意:这只是在任何两个小写字母后紧跟大写字母之间添加一个空格,因此不会将第一个单词的第一个字母作为操作请求的大写(“playerName”只是变成“player Name”)。也就是说,这是迄今为止最简洁的答案,非常适合我的需求。
  • 有点晚,但你可以添加:modified.capitalizedString
【解决方案4】:

短一点,使用 NSCharacterSet:

__block NSString *str = @"myVerySpecialPlayerName" ;

// split at uppercase letters
NSArray *splitString = [str componentsSeparatedByCharactersInSet:
     [NSCharacterSet uppercaseLetterCharacterSet]] ;

// get the uppercase letters
NSArray *upperCaseLetters = [str componentsSeparatedByCharactersInSet:
     [[NSCharacterSet uppercaseLetterCharacterSet] invertedSet]] ;

// join with two spaces
str = [splitString componentsJoinedByString:@"  "] ;
__block NSInteger offset = 0 ;

// replace each second space with the missing uppercase letter
[upperCaseLetters enumerateObjectsUsingBlock:^(NSString *character, NSUInteger idx, BOOL *stop) {
    if( [character length] > 0 ) {
        str = [str stringByReplacingCharactersInRange:NSMakeRange(idx+offset+1, 1) withString:character] ;
        offset += 2 ;
    }
}] ;

// & capitalize the first one
str = [str capitalizedString] ;

NSLog(@"%@", str) ; // "My Very Special Player Name"

【讨论】:

    【解决方案5】:

    尝试更符合 unicode 标准

    extension String {
        func camelCaseToTitleCase() -> String {
            return unicodeScalars.map(replaceCaptialsWithSpacePlusCapital).joined().capitalized
        }
        private func replaceCaptialsWithSpacePlusCapital(unichar: UnicodeScalar) -> String {
            if CharacterSet.uppercaseLetters.contains(unichar) {
                return " \(unichar)"
            }
            return "\(unichar)"
        }
    }
    

    【讨论】:

    • 我喜欢这个解决方案,但您可能想要修剪字符串的开头,因为结果句子中的第一个单词前面有一个空格。
    【解决方案6】:

    我认为您可以使用一些正则表达式来解决这个问题。看看这个类似的问题:iPhone dev: Replace uppercase characters in NSString with space and downcase

    【讨论】:

      【解决方案7】:

      虽然有点长,但是这个类对于 NSString 应该可以解决问题。它通过了我所有的测试:

      - (NSString *)splitOnCapital
      {
        // Make a index of uppercase characters
        NSRange upcaseRange = NSMakeRange('A', 26);
        NSIndexSet *upcaseSet = [NSIndexSet indexSetWithIndexesInRange:upcaseRange];
      
        // Split our camecase word
        NSMutableString *result = [NSMutableString string];
        NSMutableString *oneWord = [NSMutableString string];
        for (int i = 0; i < self.length; i++) {
          char oneChar = [self characterAtIndex:i];
          if ([upcaseSet containsIndex:oneChar]) {
            // Found a uppercase char, now save previous word
            if (result.length == 0) {
              // First word, no space in beginning
              [result appendFormat:@"%@", [oneWord capitalizedString]];
            }else {
              [result appendFormat:@" %@", oneWord];
            }
      
            // Clear previous word for new word
            oneWord = [NSMutableString string];
          }
      
          [oneWord appendFormat:@"%c", oneChar];
        }
      
        // Add last word
        if (oneWord.length > 0) {
          [result appendFormat:@" %@", oneWord];
        }
      
        return result;
      }
      

      【讨论】:

        【解决方案8】:

        我遇到了类似的问题,这里的答案帮助我创建了一个解决方案。我有一个数组,其中包含我想在 UITableView 中显示的标签列表,每行一个标签。

        我的问题是我从 SOAP 操作返回的 XML 中解析出这些标签,但我不知道字符串的格式。

        首先,我将 webstersx answer 实现到一个方法中。这很棒,但是其中一些标签以大写字母开头,而一些则以驼峰式开头(例如,一些字符串为exampleLabel,而另一些则为ExampleLabel。所以这意味着以大写字母开头的那些在前面插入了一个空格字符串。

        我通过使用 NSString 的 stringByTrimmingCharactersInSet 修剪字符串开头和结尾的空格来克服这个问题。

        下一个问题是使用的任何缩写,例如“ID”或“PNR Status”,其中显示为“ID”,“PNR Status”显示为大写字母,并且非常正确地,被选中和一个空格插入到它之前。

        我通过在我的新方法中实现类似于 emdog4 的答案的正则表达式克服了这个问题。

        这是我完成的解决方案:

        - (NSString *)formatLabel:(NSString *)label
        {
            NSMutableString *str2 = [NSMutableString string];
        
            for (NSInteger i=0; i<label.length; i++){
                NSString *ch = [label substringWithRange:NSMakeRange(i, 1)];
                if ([ch rangeOfCharacterFromSet:[NSCharacterSet uppercaseLetterCharacterSet]].location != NSNotFound) {
                    [str2 appendString:@" "];
                }
                [str2 appendString:ch];
            }
            NSString * formattedString = [str2 stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]].capitalizedString;
        
            formattedString = [formattedString stringByReplacingOccurrencesOfString:@"([A-Z]) (?![A-Z][a-z])" withString:@"$1" options:NSRegularExpressionSearch range:NSMakeRange(0, formattedString.length)];
        
            return formattedString;
        }
        

        然后我简单地调用这样的东西,例如,这将返回我格式化的字符串:

        NSString * formattedLabel = [self formatLabel:@"PNRStatus"];
        NSLog(@"Formatted Label: %@", formattedLabel);
        

        将输出:

        2013-10-10 10:44:39.888 测试项目[28296:a0b] 格式化标签:PNR 状态

        【讨论】:

          【解决方案9】:

          如果有人需要 Swift 版本:

          func camelCaseToTitleCase(s: NSString) -> String {
              var newString = ""
              if s.length > 0 {
                  newString = s.substringToIndex(1).uppercaseString
                  for i in 1..<s.length {
                      let char = s.characterAtIndex(i)
                      if NSCharacterSet.uppercaseLetterCharacterSet().characterIsMember(char) {
                          newString += " "
                      }
                      newString += s.substringWithRange(NSRange(location: i, length: 1))
                  }
              }
              return newString
          }
          

          【讨论】:

            【解决方案10】:

            虽然技术上更短,但效率更低

            NSString *challengeString = @"playerName";
            NSMutableString *rStr = [NSMutableString stringWithString:challengeString];
            
            while ([rStr rangeOfCharacterFromSet:[NSCharacterSet uppercaseLetterCharacterSet]].location != NSNotFound) {
                [rStr replaceCharactersInRange:[rStr rangeOfCharacterFromSet:[NSCharacterSet uppercaseLetterCharacterSet]] withString:[[NSString stringWithFormat:@" %@", [rStr substringWithRange:[rStr rangeOfCharacterFromSet:[NSCharacterSet uppercaseLetterCharacterSet]]]] lowercaseString]];
            }
            
            NSLog(@"%@", rStr.capitalizedString);
            

            【讨论】:

              【解决方案11】:

              不确定这是否比 websterx 短得多,但我发现使用 characterIsMember 更容易阅读和理解。如果字符串以大写字母开头,还添加了长度检查以修复空格。

              NSString *str = @"PlayerNameHowAboutALongerString";
              NSMutableString *str2 = [NSMutableString string];
              
              for (NSInteger i=0; i<str.length; i++){
                  unichar ch = [str characterAtIndex:i];
                  if ( [[NSCharacterSet uppercaseLetterCharacterSet] characterIsMember:ch]) {
                      if (str2.length > 0 ) {
                          [str2 appendString:@" "];
                      }
                  }
                  [str2 appendString:[NSString stringWithCharacters:&ch length:1]];
              }
              NSLog(@"--%@--", str2.capitalizedString);
              

              【讨论】:

                【解决方案12】:

                接受的答案对我不起作用,因为它没有将第一个字母大写,如果第一个字母已经大写,它会在开头添加一个多余的空格。这是我的改进版:

                - (NSString *)titleFromCamelCaseString:(NSString *)input
                {
                    NSMutableString *output = [NSMutableString string];
                    [output appendString:[[input substringToIndex:1] uppercaseString]];
                    for (NSUInteger i = 1; i < [input length]; i++)
                    {
                        unichar character = [input characterAtIndex:i];
                        if ([[NSCharacterSet uppercaseLetterCharacterSet] characterIsMember:character])
                        {
                            [output appendString:@" "];
                        }
                        [output appendFormat:@"%C", character];
                    }
                    return output;
                }
                

                【讨论】:

                  【解决方案13】:

                  这是 Swift 代码(webstersx 的客观 c 代码),谢谢!

                  var str: NSMutableString = "iLoveSwiftCode"
                  
                          var str2: NSMutableString = NSMutableString()
                  
                          for var i:NSInteger = 0 ; i < str.length ; i++ {
                  
                              var ch:NSString = str.substringWithRange(NSMakeRange(i, 1))
                              if(ch .rangeOfCharacterFromSet(NSCharacterSet.uppercaseLetterCharacterSet()).location != NSNotFound) {
                              str2 .appendString(" ")
                              }
                              str2 .appendString(ch)
                          }
                          println("\(str2.capitalizedString)")
                  
                      }
                  

                  【讨论】:

                    【解决方案14】:
                    NSString *input = @"playerName";
                    NSString *modified = [input stringByReplacingOccurrencesOfString:@"(?<!^)[A-Z]" withString:@" $0" options:NSRegularExpressionSearch range:NSMakeRange(0, input.length)].capitalizedString;
                    

                    【讨论】:

                      【解决方案15】:

                      Swift 2.2下的另一种解决方案

                      extension String {
                          var stringFromCamelCase:String {
                              return (self as NSString).replacingOccurrences(
                                  of: "([a-z])([A-Z])",
                                  with: "$1 $2",
                                  options: CompareOptions.regularExpressionSearch,
                                  range: NSMakeRange(0, self.characters.count)
                                  ).uppercaseFirst
                          }
                      
                          var uppercaseFirst: String {
                              return String(characters.prefix(1)).uppercased() + String(characters.dropFirst()).lowercased()
                          }
                      }
                      

                      【讨论】:

                        【解决方案16】:

                        尝试使用:

                        string.Split()
                        

                        然后使用大写字母作为标记

                        【讨论】:

                          猜你喜欢
                          • 2017-07-07
                          • 1970-01-01
                          • 1970-01-01
                          • 2011-05-08
                          • 1970-01-01
                          • 1970-01-01
                          • 2012-02-10
                          • 2013-07-24
                          • 2011-04-17
                          相关资源
                          最近更新 更多