【问题标题】:Capitalize first letter of every sentence in NSStringNSString 中每个句子的首字母大写
【发布时间】:2013-03-20 04:08:03
【问题描述】:

如何将 NSString 中每个句子的首字母大写? 例如,字符串:@"this is sentence 1. this is sentence 2! is this sentence 3? last sentence here." 应该变成:@"This is sentence 1. This is sentence 2! Is this sentence 3? Last sentence here."

【问题讨论】:

标签: objective-c nsstring


【解决方案1】:
static NSString *CapitalizeSentences(NSString *stringToProcess) {
    NSMutableString *processedString = [stringToProcess mutableCopy];


    NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en"];


    // Ironically, the tokenizer will only tokenize sentences if the first letter
    // of the sentence is capitalized...
    stringToProcess = [stringToProcess uppercaseStringWithLocale:locale];


    CFStringTokenizerRef stringTokenizer = CFStringTokenizerCreate(kCFAllocatorDefault, (__bridge CFStringRef)(stringToProcess), CFRangeMake(0, [stringToProcess length]), kCFStringTokenizerUnitSentence, (__bridge CFLocaleRef)(locale));


    while (CFStringTokenizerAdvanceToNextToken(stringTokenizer) != kCFStringTokenizerTokenNone) {
        CFRange sentenceRange = CFStringTokenizerGetCurrentTokenRange(stringTokenizer);

        if (sentenceRange.location != kCFNotFound && sentenceRange.length > 0) {
            NSRange firstLetterRange = NSMakeRange(sentenceRange.location, 1);

            NSString *uppercaseFirstLetter = [[processedString substringWithRange:firstLetterRange] uppercaseStringWithLocale:locale];

            [processedString replaceCharactersInRange:firstLetterRange withString:uppercaseFirstLetter];
        }
    }


    CFRelease(stringTokenizer);


    return processedString;
}

【讨论】:

  • 哇,这看起来是正确的解决方案!
  • 如果您更喜欢 Cocoa API,您也可以使用 -[NSString enumerateSubstringsInRange:options:usingBlock:]NSStringEnumerationBySentences 而不是 CFStringTokenizer
  • 我知道没有核心基础也有办法做到这一点!但我太累/懒得找不到它。 =P
【解决方案2】:

使用

-(NSArray *)componentsSeparatedByCharactersInSet:(NSCharacterSet *)分隔符

把你期望的新句子开头的所有分隔符(?,。,!),确保放回实际的分隔符并将数组中的第一个对象大写,然后使用

-(NSString *)componentsJoinedByString:(NSString *)分隔符

用空格分隔符将它们连接起来

为了将每个句子的第一个字母大写,对数组的所有元素运行 for 循环。

NSString *txt = @"你好!" txt = [txt stringByReplacingCharactersInRange:NSMakeRange(0,1) withString:[[txt substringToIndex:1] uppercaseString]];

【讨论】:

  • 对不起,但这仍然令人困惑。当字符串被分隔时,OP如何知道哪个字符存在! ?
  • 是的,你又是对的,我能想到任何解决方案。你有什么想法吗?
  • 还没有,实际上这是一个非常好的问题,但我猜没有任何努力!
【解决方案3】:

这似乎有效:

NSString *s1 = @"this is sentence 1. this is sentence 2! is this sentence 3? last sentence here.";

NSMutableString *s2 = [s1 mutableCopy];
NSString *pattern = @"(^|\\.|\\?|\\!)\\s*(\\p{Letter})";
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern options:0 error:NULL];
[regex enumerateMatchesInString:s1 options:0 range:NSMakeRange(0, [s1 length]) usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
    //NSLog(@"%@", result);
    NSRange r = [result rangeAtIndex:2];
    [s2 replaceCharactersInRange:r withString:[[s1 substringWithRange:r] uppercaseString]];
}];
NSLog(@"%@", s2);
// This is sentence 1. This is sentence 2! Is this sentence 3? Last sentence here.
  • "(^|\\.|\\?|\\!)" 匹配字符串或“.”、“?”或“!”的开头,
  • "\\s*" 匹配可选的空白,
  • "(\\p{Letter})" 匹配一个字母字符。

所以这个模式找到每个句子的第一个字母。 enumerateMatchesInString 枚举所有匹配项并将出现的字母替换为大写字母。

【讨论】:

    【解决方案4】:

    这是我最终想出的解决方案。我创建了一个类别来使用以下方法扩展 NSString:

        -(NSString *)capitalizeFirstLetter
    {
        //capitalizes first letter of a NSString
        //find position of first alphanumeric charecter (compensates for if the string starts with space or other special character)
        if (self.length<1) {
            return @"";
        }
        NSRange firstLetterRange = [self rangeOfCharacterFromSet:[NSCharacterSet alphanumericCharacterSet]];
        if (firstLetterRange.location > self.length)
            return self;
    
        return [self stringByReplacingCharactersInRange:NSMakeRange(firstLetterRange.location,1) withString:[[self substringWithRange:NSMakeRange(firstLetterRange.location, 1)] capitalizedString]];
    
    }
    
    -(NSString *)capitalizeSentences
    {
        NSString *inputString = [self copy];
    
        //capitalize the first letter of the string
        NSString *outputStr = [inputString capitalizeFirstLetter];
    
        //capitalize every first letter after "."
        NSArray *sentences = [outputStr componentsSeparatedByString:@"."];
        outputStr = @"";
        for (NSString *sentence in sentences){
            static int i = 0;
            if (i<sentences.count-1)
                outputStr = [outputStr stringByAppendingString:[NSString stringWithFormat:@"%@.",[sentence capitalizeFirstLetter]]];
            else
                outputStr = [outputStr stringByAppendingString:[sentence capitalizeFirstLetter]];
            i++;
        }
    
        //capitalize every first letter after "?"
        sentences = [outputStr componentsSeparatedByString:@"?"];
        outputStr = @"";
        for (NSString *sentence in sentences){
            static int i = 0;
            if (i<sentences.count-1)
                outputStr = [outputStr stringByAppendingString:[NSString stringWithFormat:@"%@?",[sentence capitalizeFirstLetter]]];
            else
                outputStr = [outputStr stringByAppendingString:[sentence capitalizeFirstLetter]];
            i++;
        }
        //capitalize every first letter after "!"
        sentences = [outputStr componentsSeparatedByString:@"!"];
        outputStr = @"";
        for (NSString *sentence in sentences){
            static int i = 0;
            if (i<sentences.count-1)
                outputStr = [outputStr stringByAppendingString:[NSString stringWithFormat:@"%@!",[sentence capitalizeFirstLetter]]];
            else
                outputStr = [outputStr stringByAppendingString:[sentence capitalizeFirstLetter]];
            i++;
        }
    
        return outputStr;
    }
    @end
    

    【讨论】:

      【解决方案5】:

      这个解决方案对我有用:

      NSMutableString *processedString = [NSMutableString stringWithString:[stringToProcess uppercaseString]];
      NSRange range = {0, [processedString length]};
      
      [processedString enumerateSubstringsInRange:range options:NSStringEnumerationBySentences usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
      
          substringRange.location++;
          substringRange.length--;
      
          NSString *replacementString = [[processedString substringWithRange:substringRange] lowercaseString];
          [processedString replaceCharactersInRange:substringRange withString:replacementString];
      }];
      

      注意:正如 fumoboy007 所述,字符串需要在开头转换为大写,否则枚举无法正常工作。

      【讨论】:

        【解决方案6】:

        我今天想这样做,并想出了一个可以包含许多句子的可变字符串“str”:

            NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"(^|\\.|\\!|\\?)\\s*[a-z]" options:0 error:NULL];
            for (NSTextCheckingResult* result in [regex matchesInString:str options:0 range:NSMakeRange(0, str.length)]) {
               NSRange rng = NSMakeRange(result.range.length+result.range.location-1, 1);
               [str replaceCharactersInRange:rng withString:[[str substringWithRange:rng] uppercaseString]];
            }
        

        我的解决方案要求我只尝试将非重音拉丁字母大写,因此使用 [a-z]。

        以前perl我觉得有点长,所以我检查了堆栈溢出。除了一个类似的答案,我想我们不能再简单了……

        【讨论】:

          猜你喜欢
          • 2015-01-25
          • 1970-01-01
          • 2017-03-30
          • 1970-01-01
          • 2011-11-13
          • 2021-07-23
          • 2022-11-16
          • 2014-07-11
          • 1970-01-01
          相关资源
          最近更新 更多