Objective-C: -[NSString wordCount]

8
以下是一个简单的实现 NSString 类别方法,它返回 self 中单词的数量,其中单词由任意数量的连续空格或换行符分隔。另外,该字符串将小于 140 个字符,因此在这种情况下,我更喜欢简单易读而不是追求性能。
@interface NSString (Additions)
- (NSUInteger)wordCount;
@end

我找到了以下解决方案: 但是,难道没有更简单的方法吗?

1
我不认为在这里有比线性搜索更好的方法。根据scanUpToCharactersFromSet的实现方式,在大多数情况下,它可能比O(n)更好。 - tjarratt
@tjarratt:我认为OP想要“最简单”的方法,不一定是最快的。 - Aidan Steele
使用NSStringEnumerationByWords在字符串枚举中按单词枚举并计数如何? - Alex Zavatone
可能是如何计算文本字符串中的单词数?的重复问题。 - Cœur
7个回答

16

为什么不直接这样做呢?

- (NSUInteger)wordCount {
    NSCharacterSet *separators = [NSCharacterSet whitespaceAndNewlineCharacterSet];
    NSArray *words = [self componentsSeparatedByCharactersInSet:separators];

    NSIndexSet *separatorIndexes = [words indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
        return [obj isEqualToString:@""];
    }];

    return [words count] - [separatorIndexes count];
}

谢谢!看起来完全正确且简单。不知道它是否高效。无论如何,在我的情况下足够好了,因为我正在构建一个iOS应用程序,而不是操作系统。 :)我喜欢它! - ma11hew28
嗯...我认为这并不完全正确。根据Xcode文档:“分隔符字符的相邻出现会在结果中产生空字符串。同样,如果字符串以分隔符字符开头或结尾,则第一个或最后一个子字符串为空。” 我不想将空字符串视为单词。例如,该方法对于@" hello "应返回1,而不是3。 - ma11hew28
太好了!它能正常工作!我还确认了在网上找到的另一个解决方案的正确性,它似乎比你的实现快大约两倍,而且仍然相当简单。因此,我将其发布为答案 - ma11hew28

11

我相信您已经找到了“最简单的”方案。然而,为了回答您最初的问题——“下面NSString类别的简单实现...”,并将其直接发布在这里以供后人参考:

@implementation NSString (GSBString)

- (NSUInteger)wordCount
{
    __block int words = 0;
    [self enumerateSubstringsInRange:NSMakeRange(0,self.length)
                             options:NSStringEnumerationByWords
                          usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {words++;}];
    return words;
}

@end

该实现不支持自定义单词的定义。 - Cœur
1
@Cœur 但是有些编程语言没有空格。 - Evgen Bodunov

9

有许多更简单的实现方式,但它们都有权衡。例如,Cocoa(但不包括Cocoa Touch)内置了单词计数:

- (NSUInteger)wordCount {
    return [[NSSpellChecker sharedSpellChecker] countWordsInString:self language:nil];
}

对于像扫描仪一样准确地计算单词数量,使用[[self componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] count]也很简单。但我发现对于较长的字符串,该方法的性能会大幅下降。

因此,这取决于您想要做出的权衡。我发现最快的方法是直接使用ICU。如果您想要最简单的方法,则使用现有代码可能比不写任何代码更简单。


4
- (NSUInteger) wordCount
{
   NSArray *words = [self componentsSeparatedByString:@" "];
   return [words count];
}

1
如果您有空格或换行符的运行,则会出现计数过多的情况。 - Obliquely
多个空格或多个换行符的计数错误 @"\n\n\n"。请参见上面的正确解决方案:https://dev59.com/0FfUa4cB1Zd3GeqPKbSU#6171439 - Cœur

1
一行Objective-C代码的版本
NSInteger wordCount = word ? ([word stringByTrimmingCharactersInSet:NSCharacterSet.whitespaceAndNewlineCharacterSet.invertedSet].length + 1) : 0;

1

看起来我在问题中提供的第二个链接仍然是最快的,而且从回顾来看,也是一个相对简单的{{link1:-[NSString wordCount]的实现}}。


该实现不支持自定义单词的定义。 - Cœur

0

Swift 3:

let words: [Any] = (string.components(separatedBy: " "))
let count = words.count

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接