【问题标题】:Searching for multiple strings in an NSString在 NSString 中搜索多个字符串
【发布时间】:2013-08-22 15:59:44
【问题描述】:

在 Objective C 中是否可以同时在一个 NSString 中搜索多个不同的字符串?

例如,我想在一个很长的字符串中搜索所有出现的字符串“good”、“great”、“awesome”、“incredible”、“fantastic”和“brilliant”。

虽然我的第一个方法是使用NSString:rangeOfString: 并循环多次(每个字符串一次),但令我震惊的是,如果字符串集越长,这可能会变得低效且缓慢。

有没有像这样搜索多个字符串的内置方法,还是我应该创建自己的方法?

编辑:结果出来了!

在找到一些时间进行基准测试后,我发现 RegEx 方法确实比循环 rangeInString 方法慢(慢了 2 倍多)。数字如下:

包含 150,000 个单词(约 1103,500 个字符)和 20 个匹配词的列表,其中存在 5412 个匹配项

NSString:rangeInString 搜索 = 231.077ms
正则表达式搜索 = 530.113ms

【问题讨论】:

  • 乍一看恐怕你将不得不“手动”迭代,但我希望有人能证明我错了
  • @GabrielePetronella 我刚刚做了 :)
  • @H2CO3,很好的答案,即使您正确指出,正则表达式可能会更慢;)
  • @GabrielePetronella 是的......我不想成为个人,但我讨厌正则表达式。他们曾经非常欺骗我,我很难忘记:P
  • 是的,当然可以,可能你需要在异步线程上多次运行–rangeOfString: 方法,这几乎是一样的。 :)

标签: iphone ios objective-c string nsstring


【解决方案1】:

让我感到震惊的是,使用更长的字符串集,这可能会变得低效且缓慢。

那么,您对它进行了基准测试吗?如果不是,那你无权判断它是“低效”和“慢”。过早的优化是邪恶的。坚持使用那些漂亮而简单的 for 循环和 - [NSString rangeOfString:] 方法。


但是:要真正回答您的问题,不可能避免手动循环。如果您将NSRegularExpressiongood|great|awesome 之类的正则表达式一起使用,那么您可以一次找到所有出现的事件。 不过,使用正则表达式可能比简单的字符串搜索要慢。

【讨论】:

  • 感谢您的建议。我并不是要判断它效率低下且速度慢,只是表明我最初想法的结构可能是浪费的,因为对于 n 个字符串的列表,它需要 n 次通过来做一些可以用更少的迭代完成的事情。看起来我会通过制作自己的方法并进行一些基准测试来享受算法练习:)
  • @sleeke 是的,实际上对代码进行基准测试比得分最高的 SO 用户一天的猜测更值得:) 这个想法是 CPU 总是更清楚它做任何人的速度有多快。
  • 同意,但是对于个人项目,早上在 SO 上发布一个问题并在工作日留下讨论是一个更好的主意;)耗时的算法设计和基准测试是最好的事情在我的业余时间:)
  • @sleeke 我不想进行非建设性的辩论,但是为这个特定案例编写一个简单的基准测试应该不会超过 10 分钟。 (另外,如果有帮助,请考虑接受我的回答。)
【解决方案2】:

正则表达式被广泛使用,实现起来会很高效。具体来说,正则表达式匹配将遍历输入字符串一次

NSRegularExpression *regex = 
  [NSRegularExpression regularExpressionWithPattern: @"(good|great|...)"  
                                            options: NSRegularExpressionCaseInsensitive
                                              error: ...];
NSArray *matches = [regex matchesInString: string
                                  options: 0
                                    range: NSMakeRange(0, [string length])];

for (NSTextCheckingResult *match in matches)
  ...

这是一个测试sn-p:

  NSString *string = @"not good nor great";

  // as above
  for (NSTextCheckingResult *match in matches)
    NSLog (@"Match: %@", match);

产生:

2013-08-22 10:21:11.644 foo[2454:707] Match: <NSSimpleRegularExpressionCheckingResult: 0x7fc954301650>{4, 4}{<NSRegularExpression: 0x7fc9543001c0> (good|great) 0x1}
2013-08-22 10:21:11.644 foo[2454:707] Match: <NSSimpleRegularExpressionCheckingResult: 0x7fc954301540>{13, 5}{<NSRegularExpression: 0x7fc9543001c0> (good|great) 0x1}

【讨论】:

    【解决方案3】:

    是的,在内部,NSString 是 unichars 的数据块。您可以检索一个指向它的指针,然后让多个队列搜索它的一部分,但您必须确保在空白字符上进行划分,以免错过两个范围的单词部分。

    【讨论】:

    • 有些 NSString 在内部不是“unichars 的数据块”。在请求字符数据时,必须将它们转换为 UTF-16。无论如何,使用原始 unicode 代码片段实现字符串搜索很复杂。
    猜你喜欢
    • 2011-09-25
    • 1970-01-01
    • 1970-01-01
    • 2011-11-26
    • 1970-01-01
    • 2021-01-16
    • 2011-11-20
    • 2011-04-28
    相关资源
    最近更新 更多