优化这个NSPredicate?

时间:2011-12-05 18:08:00

标签: iphone objective-c regex optimization nspredicate

我正在使用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];
}

2 个答案:

答案 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,我不知道。