在Objective-C中搜索字符串的最快方法是什么?

时间:2012-07-20 20:36:02

标签: iphone objective-c ios

我正在为iOS应用实现一种自动完成功能。我用于自动填充值的数据是一个逗号分隔的文本文件,大约有100,000个字符串。这就是我现在正在做的事情:

  1. 阅读文本文件,并创建一个NSArray,其中包含100,000 NSString
  2. 在用户输入时,执行[array containsObject:text]
  3. 肯定有更好/更快的方法来执行此查找。有什么想法吗?

2 个答案:

答案 0 :(得分:20)

绝对有,有!但它不是“在Objective-C中”:最有可能的是,你需要自己编写代码。

我们的想法是将您的字符串列表转换为suffix tree,这是一种允许您通过前缀非常快速地搜索的数据结构。在后缀树中搜索可能的完成非常快,但结构本身不容易构建。在互联网上快速搜索显示,目标C中没有现成的实现,但您可以port an implementation in another languageuse a C implementation,或者如果您不是,则可以编写自己的实现特别紧迫。

也许更简单的方法是按字母顺序对字符串进行排序,并对到目前为止输入的前缀运行二进制搜索。虽然效率不如后缀树,但排序数组方法对于100K字符串是可以接受的,因为你可以在十七次检查中找到正确的位置。

答案 1 :(得分:2)

最简单的可能就是二元搜索。请参阅-[NSArray indexOfObject:inSortedRange:options:usingComparator:]

特别是,我会尝试这样的事情:

  • 对保存到文件的数组进行预排序
  • 加载数组时,可能@selector(compare:)(如果您担心它被意外取消或者某些边缘情况下的Unicode排序顺序发生变化)。这应该是大约O(n),假设数组已经大部分已经排序。
  • 要查找第一个潜在匹配,[array indexOfObject:searchString inSortedRange:(NSRange){0,[array count]} options:NSBinarySearchingInsertionIndex|NSBinarySearchingFirstEqual usingComparator:@selector(compare:)]
  • 向下走数组,直到条目不再包含searchString作为前缀。您可能希望进行case / diacritic / width-insensitive比较以确定它是否是前缀(NSAnchoredSearch | NSCaseInsensitiveSearch | NSDiacriticInsensitiveSearch | NSWidthInsensitiveSearch)

这可能无法“正确”处理所有区域设置(特别是土耳其语),但既不会用compare:替换localizedCompare:,也不会用天真的字符串折叠。 (它只有9行,但是花了大约一天的工作时间才能做到正确,并且有大约40行代码和200行测试,所以我可能不应该在这里分享它。)