Количество случаев подстроки в NSString?

Как я могу получить количество раз NSString (например, @"cake") появляется в большем NSString (например, @"Cheesecake, apple cake, and cherry pie")?

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

Спасибо!

56
задан igul222 30 January 2010 в 04:10
поделиться

6 ответов

Ruby автоматически обрабатывает необработанные аргументы как имена файлов, затем открывает и считывает файлы, делая входные данные доступными для ARGF ( $ < ). По умолчанию получает чтения из ARGF. Чтобы обойти это:

$stdin.gets

Было предложено использовать STDIN вместо $ stdin , но обычно лучше использовать $ stdin .

Кроме того, после получения входных данных из ARGV , вы можете использовать:

ARGV.clear

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

-121--2634545-

Целая точка Kernel # gets - это обработка аргументов, переданных программе, как имен файлов и чтение этих файлов. Первое предложение в документации гласит:

Возвращает (и присваивает $ _) следующую строку из списка файлов в ARGV (или $ *)

Именно так получает . Если требуется выполнить чтение из определенного объекта ввода-вывода (например, $ stdin ), просто вызовите получает для этого объекта.

-121--2634548-

Это не протестировано, но должно быть хорошим началом.

NSUInteger count = 0, length = [str length];
NSRange range = NSMakeRange(0, length); 
while(range.location != NSNotFound)
{
  range = [str rangeOfString: @"cake" options:0 range:range];
  if(range.location != NSNotFound)
  {
    range = NSMakeRange(range.location + range.length, length - (range.location + range.length));
    count++; 
  }
}
98
ответ дан 26 November 2019 в 16:58
поделиться

Есть пара параметров, которыми вы могли бы сделать это. Вы могли бы позвать RansefString RangeOfString: Варианты: Диапазон: , или вы могли бы сделать что-то вроде:

NSArray * portions = [aString componentsSeparatedByString:@"cake"];
NSUInteger cakeCount = [portions count] - 1;

Редактировать Я снова думал об этом вопросе, и я написал алгоритм линейного времени, чтобы сделать поиск (Линейный до длины строки стога HayStack):

+ (NSUInteger) numberOfOccurrencesOfString:(NSString *)needle inString:(NSString *)haystack {
    const char * rawNeedle = [needle UTF8String];
    NSUInteger needleLength = strlen(rawNeedle);

    const char * rawHaystack = [haystack UTF8String];
    NSUInteger haystackLength = strlen(rawHaystack);

    NSUInteger needleCount = 0;
    NSUInteger needleIndex = 0;
    for (NSUInteger index = 0; index < haystackLength; ++index) {
        const char thisCharacter = rawHaystack[index];
        if (thisCharacter != rawNeedle[needleIndex]) {
            needleIndex = 0; //they don't match; reset the needle index
        }

        //resetting the needle might be the beginning of another match
        if (thisCharacter == rawNeedle[needleIndex]) {
            needleIndex++; //char match
            if (needleIndex >= needleLength) {
                needleCount++; //we completed finding the needle
                needleIndex = 0;
            }
        }
    }

    return needleCount;
}
23
ответ дан 26 November 2019 в 16:58
поделиться

Если семантика удаления на ссылке объекта будет делать все остальные ссылки, ссылающиеся на то, что объект будет нулевым, то вы могли бы сделать это с 2 уровнями косвения (1 больше, чем вы подсказки). Хотя обратите внимание, что, в то время как базовый объект будет уничтожен, должен быть сохранен фиксированный объем информации (достаточно для хранения ссылки), должен храниться на куче.

Все ссылки У пользователя использует, будет ссылаться на скрытую ссылку (предположительно живущий в куче) к реальному объекту. При выполнении некоторой операции на объекте (например, вызов метода или полагаться на его идентичность, Wuch, используя оператор ==), эталонная система программиста использует, будет разыменовать скрытую ссылку. При удалении объекта фактический объект будет удален из кучи, а скрытая ссылка будет установлена ​​на NULL. Таким образом, программисты ссылок увидят оценку в NULL.

Было бы задание GC, чтобы очистить эти скрытые ссылки.

-121--3714106-

Нет встроенного метода. Я бы предложил вернуть C-String и используя общий алгоритм стиля C-String для подсчета подстроки ... Если вам действительно нужно это быть быстрым.

Если вы хотите остаться в объекте C, это может помочь ссылку . Он описывает основной поиск подстроки для NSString. Если вы работаете с диапазонами, отрегулируйте и подсчитаете, у вас будет «чистый» объективное решение C ... хотя и медленно.

-1
ответ дан 26 November 2019 в 16:58
поделиться

Вот версия, выполняемая в качестве расширения NSString (та же идея, как ответ Мэтью Фласчен):

@interface NSString (my_substr_search)
- (unsigned) countOccurencesOf: (NSString *)subString;
@end
@implementation NSString (my_substring_search)
- (unsigned) countOccurencesOf: (NSString *)subString {
    unsigned count = 0;
    unsigned myLength = [self length];
    NSRange uncheckedRange = NSMakeRange(0, myLength);
    for(;;) {
        NSRange foundAtRange = [self rangeOfString:subString
                                           options:0
                                             range:uncheckedRange];
        if (foundAtRange.location == NSNotFound) return count;
        unsigned newLocation = NSMaxRange(foundAtRange); 
        uncheckedRange = NSMakeRange(newLocation, myLength-newLocation);
        count++;
    }
}
@end
<somewhere> {
    NSString *haystack = @"Cheesecake, apple cake, and cherry pie";
    NSString *needle = @"cake";
    unsigned count = [haystack countOccurencesOf: needle];
    NSLog(@"found %u time%@", count, count == 1 ? @"" : @"s");
}
3
ответ дан 26 November 2019 в 16:58
поделиться

Если вы хотите считать слова, а не только подстроки, то используйте CFStringTokenizer.

3
ответ дан 26 November 2019 в 16:58
поделиться
for(int i =0;i<htmlsource1.length-search.length;i++){
  range = NSMakeRange(i,search.length);
  checker = [htmlsource1 substringWithRange:range];

  if ([search isEqualToString:checker]) {
   count++;

  }

 }
0
ответ дан 26 November 2019 в 16:58
поделиться