iOS iPhone如何按使用频率列出UTextView中的所有关键字?

时间:2012-04-22 14:12:56

标签: iphone objective-c ios uitextview keyword

我得到了UITextView一个任意长度的文本(最多10000个字符)。我需要解析这个文本,提取所有关键字,并按照使用频率列出它们,最常用的单词在顶部,下一个,等等。我很可能在操作完成后呈现模态UITableView。

我正在考虑一种高效且有用的方法。我可以尝试使用[空格,标点符号等]形式的分隔符来分隔字符串。  这让我获得了一系列字符序列。  我可以将每个添加序列添加为NSMutableDictionary键,并在看到该单词的另一个实例后递增其计数。但是,这可能会产生300-400个字的列表,大多数频率为1.

有没有一种很好的方法来实现我所描述的逻辑?我应该尝试按字母顺序对数组进行排序并尝试某种“模糊”逻辑匹配吗? 是否有任何NSDataDetector或NSString方法可以为我做这种工作?

另一个问题是:我如何提取a,at,to,for等内容,而不是在关键字列表中列出?

如果我可以查看已经完成此任务的示例项目,那将会很棒。

谢谢!

3 个答案:

答案 0 :(得分:2)

您可以使用CFStringTokenizer来获取字边界。对于计数,您可以按照建议使用NSMutableDictionary,也可以使用效率稍高的NSCountedSet

如果您对频率为1(或其他阈值)的单词不感兴趣,则必须在计算所有单词后将其过滤掉

要忽略某些单词(a,the,for ...),您需要一个特定于文本语言的单词列表。 Wikipedia article on stop words包含几个链接,例如this CSV file

答案 1 :(得分:2)

有很多方法可以做到这一点。

您绝对应该将所有关键字添加到数组(或其他集合对象)并引用它/遍历它,以便您搜索这些关键字并仅搜索这些关键字(并且避免检查a,at,to的出现次数) ,等等。)

NSArray *keywords = [ add your keywords ];

NSString *textToSearchThrough = @" your text ";  // or load your text File here

- loop control statement here (like maybe fast enumerate), and inside this loop:
NSRange range = [textToCheckThrough rangeOfString:keywords[currentKeyword] 
                              options:NSCaseInsensitiveSearch];
if(range.location != NSNotFound) {
   // meaning, you did find it 
   // add it to a resultsArray, add 1 to this keyword's occurrenceCounter (which you must also declare and keep track of)
   // etc.
}

然后循环遍历结果数组,检查每个关键字的出现次数,清除那些出现次数为< minOccurrenceCount,并从最高到最低排序。

答案 2 :(得分:0)

我最终选择了CFStringTokenizer。我不确定下面的桥接演员是否正确,但似乎有效

-(void)listAllKeywordsInString:(NSString*)text
    {
        if(text!=nil)
        {
            NSMutableDictionary* keywordsDictionary = [[NSMutableDictionary alloc] initWithCapacity:1024];
            NSString* key = nil;
            NSLog(@"%@",text);

             NSLog(@"Started parsing: %@",[[NSDate date] description]);

            CFStringRef string =(__bridge CFStringRef)text; // Get string from somewhere

        CFStringTokenizerRef tokenizer = CFStringTokenizerCreate(kCFAllocatorDefault,  (__bridge_retained CFStringRef) text, CFRangeMake (0,CFStringGetLength((__bridge_retained CFStringRef)text)), kCFStringTokenizerUnitWord, CFLocaleCopyCurrent());

            unsigned tokensFound = 0; // or the desired number of tokens

            CFStringTokenizerTokenType tokenType = kCFStringTokenizerTokenNone;

            while(kCFStringTokenizerTokenNone != (tokenType = CFStringTokenizerAdvanceToNextToken(tokenizer)) ) {
                CFRange tokenRange = CFStringTokenizerGetCurrentTokenRange(tokenizer);
                CFStringRef tokenValue = CFStringCreateWithSubstring(kCFAllocatorDefault, string, tokenRange);

                // This is the found word
                key =(__bridge NSString*)tokenValue;

                //increment its count
                NSNumber* count = [keywordsDictionary objectForKey:key];
                if(count!=nil)
                {
                     [keywordsDictionary setValue:[NSNumber numberWithInt:1] forKey:key];
                }else {
                    [keywordsDictionary setValue:[NSNumber numberWithInt:count.intValue+1] forKey:key];
                }



                CFRelease(tokenValue);

                ++tokensFound;
            }
            NSLog(@"Ended parsing. tokens Found: %d, %@",tokensFound,[[NSDate date] description]);
            NSLog(@"%@",[keywordsDictionary description]);
            // Clean up
            CFRelease(tokenizer);

        }


    }