Количество вхождений символа в NSString - PullRequest
33 голосов
/ 02 июня 2009

У меня есть NSString или NSMutableString, и я хотел бы получить количество вхождений определенного символа.

Мне нужно сделать это для довольно большого количества символов - в данном случае заглавных букв английского алфавита - поэтому было бы неплохо, чтобы это было быстро.

Ответы [ 9 ]

100 голосов
/ 10 марта 2011

Вы можете сделать это в одну строку. Например, это подсчитывает количество пробелов:

NSUInteger numberOfOccurrences = [[yourString componentsSeparatedByString:@" "] count] - 1;
24 голосов
/ 11 апреля 2013

Попробуйте эту категорию на 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

Этот примерно в 5 раз быстрее, чем подход componentsSeparatedByString:.

17 голосов
/ 02 июня 2009

replaceOccurrencesOfString:withString:options:range: вернет количество замененных символов в NSMutableString.

[string replaceOccurrencesOfString:@"A" 
                        withString:@"B" 
                           options:NSLiteralSearch 
                             range:NSMakeRange(0, [receiver length])];
8 голосов
/ 02 июня 2009

Всякий раз, когда вы ищете вещи в NSString, попробуйте сначала использовать NSScanner.

NSString *yourString = @"ABCCDEDRFFED"; // For example
NSScanner *scanner = [NSScanner scannerWithString:yourString];

NSCharacterSet *charactersToCount = @"C" // For example
NSString *charactersFromString;

if (!([scanner scanCharactersFromSet:charactersToCount 
                          intoString:&charactersFromString])) {
    // No characters found
    NSLog(@"No characters found");
}

// should return 2 for this
NSInteger characterCount = [charactersFromString length];
6 голосов
/ 28 сентября 2014

В наше время первое, что приходит мне в голову за что-то подобное: NSCountingSet

NSString *string =@"AAATTC";

NSMutableArray *array = [@[] mutableCopy];

[string enumerateSubstringsInRange:NSMakeRange(0, [string length]) options:NSStringEnumerationByComposedCharacterSequences usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
    [array addObject:substring];
}] ;
NSCountedSet * set = [[NSCountedSet alloc] initWithArray:array];

for (NSString *nucleobase in @[@"C", @"G", @"A", @"T"]){
    NSUInteger count =  [set countForObject:nucleobase];
    NSLog(@"%@: %lu", nucleobase, (unsigned long)count);
}

журналы:

C: 1
G: 0
A: 3
T: 2
2 голосов
/ 08 апреля 2010

Ваше решение не сработало для меня, я добавил условие в цикл для увеличения numberOfChar, только если mainScanner достиг конца строки:

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

Обратите внимание, что это быстрое решение, у меня нет времени, чтобы найти элегантное решение ...

1 голос
/ 15 января 2010

Пример со сканером был сбой на iPhone. Я нашел это решение:

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

У меня это работало без сбоев. Надеюсь, это поможет!

1 голос
/ 02 июня 2009

Я бы, наверное, использовал

NSString rangeOfCharacterFromSet:

или

rangeOfCharacterFromSet:options:range::

где набор - это набор символов, который вы ищете. Возвращается с расположением первого символа, соответствующего набору. Сохраните массив или словарь и увеличьте количество символов, затем повторите.

0 голосов
/ 30 августа 2016

Вот рабочая версия Swift 3 для NSRange, Range, String и NSString! Наслаждайтесь:)

/// 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 []
        }
    }
}
...