将NSString中每个句子的首字母大写

5
我该如何将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."

你可以参考以下链接:https://dev59.com/WHE95IYBdhLWcg3wKqok - Sugan S
此外,这是一个关于如何在Objective-C中将单词或句子的首字母大写的教程:http://ioshouse.com/2012/10/how-to-capitalize-first-letter-of-a-word-or-a-sentence-in-objective-c/ - Sugan S
1
这些链接仅涉及将单个字符串的第一个字母大写,而不涉及使用不同分隔符(.,!,?)组合多个字符串的情况。 - Martin R
6个回答

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

哇,那看起来就像是正确的解决方案! - Martin R
3
如果您更喜欢Cocoa API,也可以使用-[NSString enumerateSubstringsInRange:options:usingBlock:]NSStringEnumerationBySentences代替CFStringTokenizer - Ken Thomases
我知道有一种方法可以不使用 Core Foundation 来实现它!但是我太累了/懒得去找它。=P - fumoboy007

1
这似乎有效:

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 枚举所有匹配项,并将字母的出现替换为大写字母。


1

这个解决方案对我有用:

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所提到的,字符串需要在开头转换为大写,否则枚举将无法正常工作。

这很漂亮。然而,这种首字母大写然后逐个字符小写的方式并不太"最佳化"。另外,这个枚举是否遵循当前操作系统的区域设置?我看到下面基于CFString的变体,它更长且繁琐,但比这个更高效吗? - Motti Shneor

1

使用

-(NSArray *)componentsSeparatedByCharactersInSet:(NSCharacterSet *)separator

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

-(NSString *)componentsJoinedByString:(NSString *)separator

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

要大写每个句子的第一个字母,请运行循环以遍历数组中的所有元素。

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


抱歉,但仍然很困惑。操作员怎么知道在字符串分隔时哪个字符存在?! - Janak Nirmal
是的,你又说对了,我能够为此想出任何解决方案。你有什么想法吗? - Manish Agrawal
还没有,这其实是一个非常好的问题,但我猜没有付出任何努力! - Janak Nirmal

1
这是我最终想出的解决方案。我创建了一个类别来扩展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

0
我想今天做这件事,为可变字符串“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,我认为这有点长,所以我查看了stack overflow。除了一个类似的答案外,我想我们不能再简单了...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接