Я использую 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];
}
Какие оптимизации можно применить для ускорения поиска?
Edit:
Я немного сократил свой код, удалив лишний массив комментариев. Я специально спрашиваю об оптимизации моего «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];
}