IOS - Самый эффективный способ подсчета количества слов в строке
Учитывая строку, мне нужно получить подсчет каждого слова, которое появляется в этой строке. Для этого я выделил строку в массив, словом и обыскал этот путь, но я чувствую, что поиск строки напрямую более оптимален. Ниже приведен код, который я изначально написал для решения проблемы. Тем не менее, я готов принять предложения по лучшим решениям.
NSMutableDictionary *sets = [[NSMutableDictionary alloc] init];
NSString *paragraph = [[NSString alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"text" ofType:@"txt"] encoding:NSUTF8StringEncoding error:NULL];
NSMutableArray *words = [[[paragraph lowercaseString] componentsSeparatedByString:@" "] mutableCopy];
while (words.count) {
NSMutableIndexSet *indexSet = [[NSMutableIndexSet alloc] init];
NSString *search = [words objectAtIndex:0];
for (unsigned i = 0; i < words.count; i++) {
if ([[words objectAtIndex:i] isEqualToString:search]) {
[indexSet addIndex:i];
}
}
[sets setObject:[NSNumber numberWithInt:indexSet.count] forKey:search];
[words removeObjectsAtIndexes:indexSet];
}
NSLog(@"%@", sets);
Пример:
Начальная строка:
"Это тест. Это всего лишь тест".
Результаты:
- "This" - 2
- "is" - 2
- "a" - 2
- "test" - 2
- "only" - 1
Ответы
Ответ 1
Это именно то, что означает NSCountedSet
.
Вам нужно разбить строку на слова (что iOS достаточно хорошо, чтобы дать нам функцию, так что нам не нужно беспокоиться о пунктуации) и просто добавьте каждую из них в подсчитанный набор, который отслеживает количества раз, когда каждый объект появляется в наборе:
NSString *string = @"This is a test. This is only a test.";
NSCountedSet *countedSet = [NSCountedSet new];
[string enumerateSubstringsInRange:NSMakeRange(0, [string length])
options:NSStringEnumerationByWords | NSStringEnumerationLocalized
usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop){
// This block is called once for each word in the string.
[countedSet addObject:substring];
// If you want to ignore case, so that "this" and "This"
// are counted the same, use this line instead to convert
// each word to lowercase first:
// [countedSet addObject:[substring lowercaseString]];
}];
NSLog(@"%@", countedSet);
// Results: 2012-11-13 14:01:10.567 Testing App[35767:fb03]
// <NSCountedSet: 0x885df70> (a [2], only [1], test [2], This [2], is [2])
Ответ 2
Если бы я должен был догадаться, я бы сказал NSRegularExpression
для этого. Вот так:
NSUInteger numberOfMatches = [regex numberOfMatchesInString:string
options:0
range:NSMakeRange(0, [string length])];
Этот фрагмент был взят из здесь.
Изменить 1.0:
Основываясь на том, что сказал сэр Тилл:
NSString *string = @"This is a test, so it is a test";
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
NSArray *arrayOfWords = [string componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
for (NSString *word in arrayOfWords)
{
if ([dictionary objectForKey:word])
{
NSNumber *numberOfOccurences = [dictionary objectForKey:word];
NSNumber *increment = [NSNumber numberWithInt:(1 + [numberOfOccurences intValue])];
[dictionary setValue:increment forKey:word];
}
else
{
[dictionary setValue:[NSNumber numberWithInt:1] forKey:word];
}
}
Вы должны быть осторожны с:
- Знаки пунктуации. (рядом с другими словами)
- слова UpperCase и слова lowerCase.
Ответ 3
Я думаю, что действительно плохая идея, что вы пытаетесь найти слова среди длинного абзаца с циклом. Вы должны использовать регулярное выражение для этого! Я знаю, что сначала нелегко это изучить, но это действительно стоит того знать! Взгляните на этот случай Используйте регулярное выражение для поиска/замены подстроки в NSString