我正在使用NSPredicate
来搜索NSManagedObject
个实例的数组。每个“文章”都有一个“标题”,一个“内容”,并且可能与几个“标签”匹配。
我想使用正则表达式来匹配文章的内容,而另一个搜索运算符则适用于其他所有内容。问题是我的搜索速度非常慢。这就是我所拥有的:
- (void) filterArrayWithSearchTerm:(NSString *)searchString andScopeIndex:(NSInteger)scopeIndex{
//
// Grab a local copy of the search string.
// This is done simply for convenience in the
// following set of if statements.
//
NSMutableString *modifiedSearchString = [searchString mutableCopy];
NSPredicate *predicate;
//1 is "content" and 3 is "all"
if(scopeIndex == 1 || scopeIndex == 3){
NSInteger length = [searchString length];
NSString *vowelsAsRegex = @"[\u0591-\u05c4]?[\u0591-\u05c4]?";
//If our search includes the body of the text
for (int i = length; i > 0; i--) {
[modifiedSearchString insertString:vowelsAsRegex atIndex:i];
}
[modifiedSearchString insertString:@".*" atIndex:0];
[modifiedSearchString appendString:@".*"];
}
//
// Depending on the selected scope bar option
// we perform a "MATCHES" search.
//
// For searching properties of related entities, we use the ANY keyword
//
//NSLog(@"Regex: %@", modifiedSearchString);
if (scopeIndex == 0) {
predicate = [NSPredicate predicateWithFormat:@"articleTitle CONTAINS[cd] %@", modifiedSearchString];
}else if (scopeIndex == 1) {
predicate = [NSPredicate predicateWithFormat:@"articleContent CONTAINS[cd] %@", modifiedSearchString];
}else if (scopeIndex == 2){
predicate = [NSPredicate predicateWithFormat:@"ANY tags.tagText MATCHES[cd] %@", modifiedSearchString];
}else{
predicate = [NSPredicate predicateWithFormat:@"(ANY tags.tagText CONTAINS[cd] %@) OR (articleTitle CONTAINS[cd] %@) OR (articleContent MATCHES[cd] %@)", modifiedSearchString, modifiedSearchString, modifiedSearchString];
}
[modifiedSearchString release];
NSMutableArray *unfilteredResults = [[[[self.fetchedResultsController sections] objectAtIndex:0] objects] mutableCopy];
//
// Ensure that we have an array to work with.
//
if (self.filteredArray == nil) {
self.filteredArray = [[[NSMutableArray alloc ] init] autorelease];
}
//
// Clear out any existing objects from earlier.
//
[filteredArray removeAllObjects];
//
// Perform the filtering by looping
// through the articles and checking
// it against the predicate.
//
for (Article *article in unfilteredResults) {
if ([predicate evaluateWithObject:article])
[self.filteredArray addObject:article];
}
//
// Release the unfiltered array.
//
[unfilteredResults release];
}
可以应用哪些优化来加快搜索速度?
修改
我稍微删除了我的代码,删除了额外的数组注释。我特别询问优化我的NSPredicate“包含”和“匹配”,看看是否有更快的方法来实现它们。这是新代码:
- (void) filterArrayWithSearchTerm:(NSString *)searchString andScopeIndex:(NSInteger)scopeIndex{
NSMutableString *modifiedSearchString = [searchString mutableCopy];
NSPredicate *predicate;
if(scopeIndex == 1 || scopeIndex == 3){
NSInteger length = [searchString length];
NSString *vowelsAsRegex = @"[\u0591-\u05c4]?[\u0591-\u05c4]?"; //Trop: \u0591-\u05AF Nekudot: \u05b0-\u05c
for (int i = length; i > 0; i--) {
[modifiedSearchString insertString:vowelsAsRegex atIndex:i];
}
[modifiedSearchString insertString:@".*" atIndex:0];
[modifiedSearchString appendString:@".*"];
}
if (scopeIndex == 0) {
predicate = [NSPredicate predicateWithFormat:@"articleTitle CONTAINS[cd] %@", modifiedSearchString];
}else if (scopeIndex == 1) {
predicate = [NSPredicate predicateWithFormat:@"articleContent CONTAINS[cd] %@", modifiedSearchString];
}else if (scopeIndex == 2){
predicate = [NSPredicate predicateWithFormat:@"ANY tags.tagText MATCHES[cd] %@", modifiedSearchString];
}else{
predicate = [NSPredicate predicateWithFormat:@"(ANY tags.tagText CONTAINS[c] %@) OR (articleTitle CONTAINS[c] %@) OR (articleContent MATCHES[cd] %@)", modifiedSearchString, modifiedSearchString, modifiedSearchString];
}
[modifiedSearchString release];
NSMutableArray *unfilteredResults = [[[[self.fetchedResultsController sections] objectAtIndex:0] objects] mutableCopy];
[unfilteredResults filterUsingPredicate:predicate];
self.filteredArray = unfilteredResults;
[unfilteredResults release];
}
答案 0 :(得分:1)
追加;而不是做很多插入:
NSMutableString *modifiedSearchString = [[NSMutableString alloc] init];
if(scopeIndex == 1 || scopeIndex == 3)
{
NSString *vowelsAsRegex = @"[\u0591-\u05c4]?[\u0591-\u05c4]?";
[modifiedSearchString appendString:@".*"];
for (int i = 0, length = [searchString length]; i < l; i++)
{
[modifiedSearchString appendString:vowelsAsRegex];
[modifiedSearchString appendString:[searchString characterAtIndex:i]];
}
[modifiedSearchString appendString:@".*"];
}
答案 1 :(得分:0)
这一行:
NSString *vowelsAsRegex = @"[\u0591-\u05c4]?[\u0591-\u05c4]?";
应该等于这个:
NSString *vowelsAsRegex = @"[\u0591-\u05c4]{0,2}";
那应该减少RegEx匹配中的分支数量,但是tbh,我不知道。