Number of Occurrences of a Character in NSString

2019-01-07 17:47发布

I have an NSString or NSMutableString and would like to get the number of occurrences of a particular character.

I need to do this for quite a few characters -- uppercase English characters in this case -- so it would be nice for it to be quick.

9条回答
来,给爷笑一个
2楼-- · 2019-01-07 18:26

Here is a Swift 3 working version, for NSRange, Range, String and NSString! Enjoy :)

/// All ranges using NSString and NSRange
/// Is usually used together with NSAttributedString

extension NSString {
    public func ranges(of searchString: String, options: CompareOptions = .literal, searchRange: NSRange? = nil) -> [NSRange] {
        let searchRange = searchRange ?? NSRange(location: 0, length: self.length)
        let subRange = range(of: searchString, options: options, range: searchRange)
        if subRange.location != NSNotFound {

            let nextRangeStart = subRange.location + subRange.length
            let nextRange = NSRange(location: nextRangeStart, length: searchRange.location + searchRange.length - nextRangeStart)
            return [subRange] + ranges(of: searchString, options: options, searchRange: nextRange)
        } else {
            return []
        }
    }
}

/// All ranges using String and Range<Index>
/// Is usually used together with NSAttributedString

extension String {
    public func ranges(of searchString: String, options: CompareOptions = [], searchRange: Range<Index>? = nil ) -> [Range<Index>] {
        if let range = range(of: searchString, options: options, range: searchRange, locale: nil) {

            let nextRange = range.upperBound..<(searchRange?.upperBound ?? endIndex)
            return [range] + ranges(of: searchString, searchRange: nextRange)
        } else {
            return []
        }
    }
}
查看更多
迷人小祖宗
3楼-- · 2019-01-07 18:31

Your solution did not work for me, I added a condition in the loop to increment numberOfChar only if mainScanner has reached the end of the string :

NSString *yourString = @"ABCCDEDRFFED"; // For example
NSScanner *mainScanner = [NSScanner scannerWithString:yourString];
NSString *temp;
NSInteger numberOfChar=0;
while(![mainScanner isAtEnd])
{
   [mainScanner scanUpToString:@"C" intoString:&temp];
   if(![mainScanner isAtEnd]) {
      numberOfChar++;
      [mainScanner scanString:@"C" intoString:nil];
   }
}

Note that this is a quick fix, I don't have time to make an elegant solution...

查看更多
够拽才男人
4楼-- · 2019-01-07 18:32

Try this category on NSString:

@implementation NSString (OccurrenceCount)

- (NSUInteger)occurrenceCountOfCharacter:(UniChar)character
{
    CFStringRef selfAsCFStr = (__bridge CFStringRef)self;

    CFStringInlineBuffer inlineBuffer;
    CFIndex length = CFStringGetLength(selfAsCFStr);
    CFStringInitInlineBuffer(selfAsCFStr, &inlineBuffer, CFRangeMake(0, length));

    NSUInteger counter = 0;

    for (CFIndex i = 0; i < length; i++) {
        UniChar c = CFStringGetCharacterFromInlineBuffer(&inlineBuffer, i);
        if (c == character) counter += 1;
    }

    return counter;
}

@end

This one is approximately 5 times faster than the componentsSeparatedByString: approach.

查看更多
登录 后发表回答