计算NSString中的单词数

时间:2011-03-03 06:41:05

标签: iphone ipad nsstring count uitextview

我正在尝试为使用UITextView的应用实现字数统计功能。

英语中两个单词之间有一个空格,所以很容易计算英语单词中的单词数。 中文和日文单词计数会出现问题,因为通常,整个句子中没有任何空格。

我在iPad中检查了三个具有字数统计功能的不同文本编辑器,并将它们与MS Words进行比较。

例如,这里有一系列日文字符,意思是世界的想法:世界(世界)の('s)アイデア(想法)

世界のアイデア

1)用于iPad和MS的页面单词将每个字符计为一个单词,因此它包含7个单词。

2)iPad文本编辑器P ***将整个计为一个单词 - >他们只是用空间来分隔单词。

3)iPad文本编辑器i ***将它们视为三个单词 - >我相信他们使用CFStringTokenizer和kCFStringTokenizerUnitWord,因为我可以得到相同的结果)

我在互联网上进行过研究,而Pages和MS Words的单词计数似乎是正确的,因为每个汉字都有意义。

我找不到任何类似于Pages或MS Words这样的词的类,从头开始实现它会非常困难,因为除了日语和中文之外,iPad还支持很多不同的外语。 /强>

我认为带有kCFStringTokenizerUnitWord的CFStringTokenizer是最好的选择。

有没有办法在NSString中计算像Pages和MSWords这样的单词?

谢谢

7 个答案:

答案 0 :(得分:3)

我建议继续使用CFStringTokenizer。因为它是平台功能,所以将通过平台升级进行升级。苹果公司的许多人都在努力反映真正的文化差异。常规开发人员很难知道。

这很难,因为这本身并不是一个编程问题。这是一个人类文化语言问题。每种文化都需要一名人类语言专家。对于日本人,您需要日本文化专家。但是,我不认为日本人需要认真对待字数统计功能,因为正如我所听到的,本身的概念在日本文化中并不那么重要。你应该首先定义单词的概念。

我无法理解你为什么要强迫字数的概念进入字符数。您实例化的汉字。这相当于将universe计为2个单词,方法是按意义分为uni + verse。甚至不是逻辑。通过它的含义拆分词的含义有时是完全错误的,而且对词的定义毫无用处。因为文字的定义本身是不同的。用我的语言韩语,单词只是一个正式单位,而不是意义单位。每个单词与每个含义相匹配的想法只适用于罗马字符文化。

如果您认为需要,请为东亚地区的用户提供字符计数等其他功能。使用-[NSString length]方法计算unicode字符串中的字符非常容易。

我是韩语演讲者(所以可能不在你的情况下:)在很多情况下我们会计算字符而不是单词。事实上,我从来没有看到人们一生都在计算单词。我在MS字上嘲笑字数统计功能,因为我猜不会有人会用它。 (但是现在我知道它在罗马字符文化中很重要。)我只使用了一次字数统计功能才知道它确实有效:)我相信这在中文或日文中是相似的。也许日本用户使用单词count,因为他们的基本字母与罗马字符类似,没有组成概念。然而,他们大量使用汉字,这是完全合成的,以角色为中心的系统。

如果你使单词计数功能在这些语言上有很大的作用(人们使用它甚至不觉得有必要将句子分成较小的正式单位!),很难想象有人使用它。没有语言专家,该功能不应该纠正。

答案 1 :(得分:2)

如果您的字符串不包含标识分词符号(如空格)的标记,那么这是一个非常难的问题。我所知道的一种尝试解决字谜的方法是:

在字符串的开头,您以一个字符开头。这是一个字吗?它可以是像“A”这样的单词,但它也可以是“AN”或“ANALOG”之类的单词的一部分。因此,考虑到所有的字符串,必须做出关于什么是单词的决定。您可以考虑下一个字符,看看是否可以从您认为可能找到的第一个单词后面的第一个字符开始生成另一个单词。如果你决定单词是“A”并且你留下“NALOG”那么你很快就会发现没有更多的单词可以找到。当你开始在字典中找到单词时(见下文),你知道你正在做出正确的选择,在哪里打破单词。当你停止查找单词时,你知道你做出了错误的选择而你需要回溯。

其中很大一部分是字典足以包含您可能遇到的任何字词。英语资源将是TWL06或SOWPODS或其他拼字游戏词典,包含许多模糊的单词。你需要大量的内存才能做到这一点,因为如果你对一个包含所有可能单词的简单数组检查单词,你的程序运行速度会非常慢。如果您解析字典,将其保留为plist并重新创建字典,您的检查将足够快,但它将需要更多的磁盘空间和更多的内存空间。其中一个大的拼字游戏词典可以扩展到大约10MB,实际的单词作为键,一个简单的NSNumber作为值的占位符 - 你不关心它的价值是什么,只是键中存在键,它告诉你该词被认为是有效的。

如果您按照计算维护一个数组,那么当您添加包含最后一个字符的最后一个单词时,您将以凯旋的方式执行[数组计数],但您也可以轻松地进行回溯。如果在某些时候你停止找到有效的单词,你可以从数组中弹出lastObject并在字符串的开头替换它,然后开始寻找替代单词。如果这不能让你回到正确的轨道上弹出另一个词。

我会继续进行实验,在你解析字符串时寻找潜在的三个单词 - 当你识别出三个潜在的单词时,取出第一个单词,将它存储在数组中并寻找另一个单词。如果你发现这样做的速度太慢而且考虑到前面只有两个单词就会得到OK结果,将其降为两个。如果你发现你的单词划分策略运行了太多死胡同,那么就提前考虑增加单词的数量。

另一种方法是采用自然语言规则 - 例如“A”和“NALOG”看起来可能正常,因为辅音跟随“A”,但“A”和“ARDVARK”将被排除,因为它是正确的一个单词以元音开头跟随“AN”,而不是“A”。这可能会变得像你想要的那样复杂 - 我不知道这在日语中是否变得更简单,但是肯定会有像“ma su”这样的常见动词结尾。

(编辑:开始赏金,如果我的方式不是,我想知道最好的方法。)

答案 2 :(得分:1)

如果您使用的是iOS 4,则可以执行类似

的操作
__block int count = 0;
[string enumerateSubstringsInRange:range
                           options:NSStringEnumerationByWords
                        usingBlock:^(NSString *word,
                                     NSRange wordRange,
                                     NSRange enclosingRange,
                                     BOOL *stop)
    {
        count++;
    }
];

NSString class reference

中的更多信息

还有WWDC 2010 session,编号110,关于高级文本处理,解释了这一点,大约10分钟左右。

答案 3 :(得分:0)

  

我认为带有kCFStringTokenizerUnitWord的CFStringTokenizer是最好的选择。

这是正确的,你必须遍历文本并简单地计算在途中遇到的单词标记的数量。

答案 4 :(得分:0)

不是中国/日本本土人,但这是我的2点。

每个汉字都有意义,但一个词的概念是字母/字符的组合来表示一个想法,不是吗?

从这个意义上讲,“sekai no aidia”中可能有3个单词(如果你不计算像NO / GA / DE / WA这样的粒子,那么就有2个单词)。与英语相同 - “世界的想法”是两个词,而“世界的想法”是3,让我们忘记所需的“嘿嘿”。

在我看来,计算单词在非罗马语言中并不那么有用,类似于Eonil所提到的。计算这些语言的字符数可能更好。查看中国/日本母语人士并查看他们的想法。

如果我这样做,我会用空格和粒子(至少对日语,韩语)和计数标记来标记字符串。不确定中文..

答案 5 :(得分:0)

使用日语,您可以创建一个语法分析器,我认为它与中文相同。然而,这说起来容易做起来难,因为自然语言往往有许多例外,但这并非不可能。

请注意,由于您必须在能够计算单词之前解析每个句子,因此效率不高。

我建议使用解析器编译器,而不是自己构建一个,至少可以开始专注于编写语法,而不是自己创建解析器。它效率不高,但应该完成工作。

还有一个回退算法,以防你的语法没有正确解析输入(也许输入真的没有意义开始)你可以使用字符串的长度来使你更容易。

如果您构建它,那么您可能有市场机会将其用作日语/中文业务规则的自然语言域特定语言。

答案 6 :(得分:-1)

只需使用长度方法:

[@"世界のアイデア" length];  // is 7

话虽如此,作为日语发言人,我认为3是正确答案。