获取NSString中所有大写字母的NSRange对象数组的最快方法? [英] Fastest way to get array of NSRange objects for all uppercase letters in an NSString?

查看:65
本文介绍了获取NSString中所有大写字母的NSRange对象数组的最快方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于给定NSString中每个大写字母的位置,我需要NSRange对象,以输入到自定义属性字符串类的方法中.

I need NSRange objects for the position of each uppercase letter in a given NSString for input into a method for a custom attributed string class. 

当然有很多方法可以完成此任务,例如rangeOfString:options:使用NSRegularExpressionSearch或使用RegexKitLite在遍历字符串时分别获取每个匹配项.

There are of course quite a few ways to accomplish this such as rangeOfString:options: with NSRegularExpressionSearch or using RegexKitLite to get each match separately while walking the string. 

执行此任务最快的方法是什么?

What would be the fastest performing approach to accomplish this task?

推荐答案

最简单的方法可能是将 -rangeOfCharacterFromSet:options:range: [NSCharacterSet uppercaseLetterCharacterSet] 一起使用.通过修改搜索范围,可以轻松查找所有大写字母.类似于以下内容的方法可以为您提供所有范围的NSArray(编码为NSValues):

The simplest way is probably to use -rangeOfCharacterFromSet:options:range: with [NSCharacterSet uppercaseLetterCharacterSet]. By modifying the range to search over with each call, you can find all of the uppercase letters pretty easily. Something like the following will work to give you an NSArray of all ranges (encoded as NSValues):

- (NSArray *)rangesOfUppercaseLettersInString:(NSString *)str {
    NSCharacterSet *cs = [NSCharacterSet uppercaseLetterCharacterSet];
    NSMutableArray *results = [NSMutableArray array];
    NSRange searchRange = NSMakeRange(0, [str length]);
    NSRange range;
    while ((range = [str rangeOfCharacterFromSet:cs options:0 range:searchRange]).location != NSNotFound) {
        [results addObject:[NSValue valueWithRange:range]];
        searchRange = NSMakeRange(NSMaxRange(range), [str length] - NSMaxRange(range));
    }
    return results;
}

请注意,这不会将相邻范围合并为一个范围,但这很容易添加.

Note, this will not coalesce adjacent ranges into a single range, but that's easy enough to add.

这是基于NSScanner的替代解决方案:

Here's an alternative solution based on NSScanner:

- (NSArray *)rangesOfUppercaseLettersInString:(NSString *)str {
    NSCharacterSet *cs = [NSCharacterSet uppercaseLetterCharacterSet];
    NSMutableArray *results = [NSMutableArray array];
    NSScanner *scanner = [NSScanner scannerWithString:str];
    while (![scanner isAtEnd]) {
        [scanner scanUpToCharactersFromSet:cs intoString:NULL]; // skip non-uppercase characters
        NSString *temp;
        NSUInteger location = [scanner scanLocation];
        if ([scanner scanCharactersFromSet:cs intoString:&temp]) {
            // found one (or more) uppercase characters
            NSRange range = NSMakeRange(location, [temp length]);
            [results addObject:[NSValue valueWithRange:range]];
        }
    }
    return results;
}

与上一个字符不同,此字符确实将相邻的大写字符合并为一个范围.

Unlike the last, this one does coalesce adjacent uppercase characters into a single range.

编辑:如果您正在寻找绝对速度,则此速度可能是此处介绍的3中最快的速度,同时仍保留正确的unicode支持(请注意,我没有尝试编译此代码):

Edit: If you're looking for absolute speed, this one will likely be the fastest of the 3 presented here, while still preserving correct unicode support (note, I have not tried compiling this):

// returns a pointer to an array of NSRanges, and fills in count with the number of ranges
// the buffer is autoreleased
- (NSRange *)rangesOfUppercaseLettersInString:(NSString *)string count:(NSUInteger *)count {
    NSMutableData *data = [NSMutableData data];
    NSUInteger numRanges = 0;
    NSUInteger length = [string length];
    unichar *buffer = malloc(sizeof(unichar) * length);
    [string getCharacters:buffer range:NSMakeRange(0, length)];
    NSCharacterSet *cs = [NSCharacterSet uppercaseLetterCharacterSet];
    NSRange range = {NSNotFound, 0};
    for (NSUInteger i = 0; i < length; i++) {
        if ([cs characterIsMember:buffer[i]]) {
            if (range.location == NSNotFound) {
                range = (NSRange){i, 0};
            }
            range.length++;
        } else if (range.location != NSNotFound) {
            [data appendBytes:&range length:sizeof(range)];
            numRanges++;
            range = (NSRange){NSNotFound, 0};
        }
    }
    if (range.location != NSNotFound) {
        [data appendBytes:&range length:sizeof(range)];
        numRanges++;
    }
    if (count) *count = numRanges;
    return [data bytes];
}

这篇关于获取NSString中所有大写字母的NSRange对象数组的最快方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆