【问题标题】:Improve search performance in objective-c提高objective-c中的搜索性能
【发布时间】:2018-11-22 08:20:05
【问题描述】:

我正在一个函数中搜索大约 100k 个字符串:

results = [NSMutableArray new];
for (int n = 0; n < (int)_donkey.searchStrings.count; n++){
    if ([[_donkey.searchStrings[n] lowercaseString] rangeOfString:tf.text.lowercaseString].location != NSNotFound){
        [results addObject:_donkey.formattedStrings[n]];
    }
}

其中tf.text 是用户在UITextField 中输入的文本。性能很慢,我觉得有一种更好的搜索方式,而不是直接的字符串比较。

被搜索的字符串格式如下:“attributeA attributeB attributeC”,所以如果在attributeA之前输入attributeB,它不会作为结果出现,这是应该的。

【问题讨论】:

  • 也许你可以用NSPredicate和/或NSRegularExpression来做到这一点。
  • @Koen 这两者都会比有目的地编写的代码慢得多。
  • 与您的性能问题无关,但不要在循环中使用intcount 返回NSUInteger。数组访问使用NSUInteger。所以使用NSUInteger 作为循环变量(并去掉演员表)。
  • @rmaddy 谢谢,出于某些(非逻辑)原因,我更喜欢整数,但应该学会放弃不良的编码习惯 :)

标签: ios objective-c search nsstring


【解决方案1】:

一些显而易见的事情:

  • 不要通过循环多次调用searchStrings 属性getter。调用一次并将其缓存在局部变量中。
  • 不要在每次循环迭代时调用 count getter。
  • 不要在每次循环迭代时调用 text getter。
  • 如果您要使用lowercaseString,请不要在每次循环迭代时在文本字段的字符串上调用它。但请看下一项。
  • 不要使用lowercaseString。使用-rangeOfString:options:NSCaseInsensitiveSearch 选项、-localizedCaseInsensitiveContainsString:-localizedStandardContainsString:。它们不仅可能更快,而且更正确。 (语言可能很奇怪,比较小写字符串可能不一定与不区分大小写的比较相同。)
  • 由于您是从searchStrings 的匹配元素的索引构建一个数组,因此您可以使用-indexesOfObjectsWithOptions:passingTest: 来构建一组匹配元素的索引。在这种情况下,您不必自己编写(较慢的)枚举代码。您还可以在选项中指定NSEnumerationConcurrent 以允许框架使用多个线程来执行搜索。设置好索引后,您将使用-objectsAtIndexes:formattedStrings 获取相应元素的数组。同样,该框架可以比您在可变数组中一次构建一个元素的方法更快地做到这一点。 (感谢@rmaddy 的建议。)

被搜索的字符串格式如下:“attributeA attributeB attributeC”,所以如果在attributeA之前输入attributeB,它不会作为结果出现,这是应该的。

我不明白你问题的这一部分,它似乎是关于正确性而不是性能。所以:1)在关注性能之前先获得正确性。使错误的算法更快没有意义。 2) 这应该是一个单独的问题。

【讨论】:

  • 一个更明显的建议 - 用至少一个 for in 循环替换慢速 C 风格的 for 循环,但更好的是,使用 enumerateObjectsWithOptions: 可能使用 NSEnumerationConcurrent 选项。
  • @rmaddy:是的,尽管这与排序数组优化相冲突。而且,由于他正在构建一个新数组,他可以使用-indexesOfObjectsWithOptions:passingTest:,然后使用-objectsAtIndexes:。这也可能比结果数组的逐个元素累积更快。
  • 我的意思是评论你关于排序的建议。这似乎不适用于这种情况,因为目标是查找列表中包含搜索文本的每个字符串。排序不会帮助这样的搜索。如果目标是执行前缀搜索,那么排序会很有用。
  • 啊,真的。编辑删除。
猜你喜欢
  • 2018-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-30
相关资源
最近更新 更多