Pen*_*One 4 iphone objective-c nsstring nspredicate ios
我有大量的字符串,我正在搜索是否存在给定的子字符串.似乎有两种合理的方法可以做到这一点.
选项1:使用NSString方法rangeOfSubstring并测试是否.location存在:
NSRange range = [string rangeOfSubstring:substring];
return (range.location != NSNotFound);
Run Code Online (Sandbox Code Playgroud)
选项2.使用NSPredicate语法CONTAINS:
NSPredicate *regex = [NSPredicate predicateWithFormat:@"SELF CONTAINS %@", substring];
return ([regex evaluateWithObject:string] == YES)
Run Code Online (Sandbox Code Playgroud)
哪种方法更好,还是有一个很好的选项3,我完全不知道?不,我不确定我的意思是"更好",但可能我的意思是在迭代很多很多时更快string.
joh*_*hne 18
您应该对使用的任何解决方案进行基准测试和计时,NSPredicate因为根据我的经验,这NSPredicate可能非
为简单起见,我会选择一种简单for(NSString *string in stringsArray) { }的循环方式.循环体将包含一个简单的rangeOfSubstring检查.通过使用CFStringFind(),您可以将此性能提高几个百分点,但如果您搜索大量字符串,则只会看到一个好处.使用的优点CFStringFind()是可以避免(非常小的)Objective-C消息调度开销.同样,当你搜索"很多"字符串时(通常会改变一些"很多"的值),通常只能转换到那个,并且你应该始终确定基准.rangeOfString:如果可以的话,更喜欢更简单的Objective-C 方式.
更复杂的方法是使用^ Blocks功能和NSEnumerationConcurrent选项. NSEnumerationConcurrent只是提示您希望枚举在可能的情况下同时发生,并且如果实现可以不支持并发枚举,则可以自由忽略此提示.但是,您的标准NSArray很可能会实现并发枚举.在实践中,这具有划分所有对象NSArray并将它们划分为可用CPU的效果.您需要注意如何改变跨多个线程的^ Block访问的状态和对象.这是一种可行的方法:
// Be sure to #include <libkern/OSAtomic.h>
__block volatile OSSpinLock spinLock = OS_SPINLOCK_INIT;
__block NSMutableArray *matchesArray = [NSMutableArray array];
[stringsToSearchArray enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSRange matchedRange = [obj rangeOfString:@"this"];
if(matchedRange.location != NSNotFound) {
OSSpinLockLock((volatile OSSpinLock * volatile)&spinLock);
[matchesArray addObject:obj];
OSSpinLockUnlock((volatile OSSpinLock * volatile)&spinLock);
}
}];
// At this point, matchesArray will contain all the strings that had a match.
Run Code Online (Sandbox Code Playgroud)
这使用轻量级OSSpinLock来确保一次只有一个线程可以访问和更新matchesArray.你也可以在CFStringFind()这里使用同样的建议.
此外,您应该意识到,rangeOfString:它本身不会匹配"单词边界".在上面的例子中,我使用了this与字符串匹配的单词,A paleolithist walked in to the bar...即使它不包含单词this.
这个小皱纹的最简单的解决方案是使用ICU正则表达式并利用它的"增强的断字"功能.为此,您有以下几种选择:
NSRegularExpression,目前仅适用于> 4.2或> 4.3 iOS(我忘了哪个).NSPredicate,通过SELF MATCHES '(?w)\b...\b'.这样做的好处是它不需要额外的东西(即RegexKit Lite),并且可用于所有(?)版本的Mac OS X和iOS> 3.0.以下代码显示如何通过以下方式在ICU正则表达式中使用增强的分词功能NSPredicate:
NSString *searchForString = @"this";
NSString *regexString = [NSString stringWithFormat:@".*(?w:\\b\\Q%@\\E\\b).*", searchForString];
NSPredicate *wordBoundaryRegexPredicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regexString];
NSArray *matchesArray = [stringsToSearchArray filteredArrayUsingPredicate:wordBoundaryRegexPredicate];
Run Code Online (Sandbox Code Playgroud)
您可以搜索不区分大小写通过更换(?w:在regexString用(?wi:.
正如你感兴趣的那样,正则表达式基本上是这么说的
.*(?w:...).*说"在(?w:...)零件之前和之后匹配"(即,我们只对(?w:...)零件感兴趣).(?w:...) 说"在括号内打开ICU增强的断字/查找功能".\\b...\\b(这实际上只是一个反斜杠,任何反斜杠必须在@""字符串内部时反斜杠转义)说"匹配单词边界".\\Q...\\E说"将文本立即开始处理\Q,直到\E作为文字文本(认为"引用"和"结束")".换句话说,"引用文字文本"中的任何字符都没有其特殊的正则表达式含义.原因\Q...\E是你可能想要匹配文字字符searchForString.如果没有这个,searchForString将被视为正则表达式的一部分.作为一个例子,如果searchForString是this?,那么没有\Q...\E它将不匹配文字字符串this?,但是或者,thi或者this,这可能不是你想要的.:)
| 归档时间: |
|
| 查看次数: |
3191 次 |
| 最近记录: |