使用nspredicates优化搜索查询

时间:2013-10-03 05:12:34

标签: ios optimization nsarray nspredicate

这个问题已经提出了很多,但我似乎无法再进一步优化这段搜索代码。

这个filterSet数组有大约1000个项目,并且需要8秒才能在非模拟器iPad上重现结果(模拟器在不到一秒的时间内显示结果):

for(NSString *rowID in [self.filterSet array]) {

    self.rowResults = [self.filteredResults filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"rowID = %@", rowID]];
    self.rowResults = [self.rowResults valueForKey:@"value"];
    self.duplicateValueSet = [NSOrderedSet orderedSetWithArray:self.rowResults];
    filterCount = [[self.resultsArray filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF = %@", rowID]] count];

    if([self.duplicateValueSet count] != filterCount) 
        filterCount -= abs([self.duplicateValueSet count] - filterCount);

    if(filterCount == matchingCount)
        [self.results addObject:rowID];
}

优化此查询的任何建议?大多数搜索都在所有过滤器和谓词排序中进行。感谢。

编辑:所以我删除了for循环中的很多代码,发现罪魁祸首是第一行

self.rowResults = [self.filteredResults filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"rowID = %@", rowID]];

这是出于某种原因需要7秒才能执行。是否有更快/更有效的方法来创建谓词以匹配rowID字符串?我已经考虑过使用makeobjectsperformselector NSArray方法但由于某种原因我得到了NSCFNumber无法识别的选择器问题(这就是说我的数组有NSNumbers而不是NSStrings)

1 个答案:

答案 0 :(得分:0)

所以我的初始算法运行在O(N ^ 2),这几乎和它(实际上)一样糟糕。

我最终使用NSDictionary映射键/值,以便我可以在第一个for循环的第一遍中轻松引用它们:

NSMutableDictionary * filteredResultsDict = [[[NSMutableDictionary alloc] init] autorelease];

for (int i = 0; i < [filteredResults count]; i++) {
    NSString *key = [[filteredResults objectAtIndex:i] valueForKey:@"rowID"];
    NSMutableArray *filtersArray = [NSMutableArray array];
    NSMutableArray *tempArray = [filteredResultsDict objectForKey:key];

    if (tempArray != nil || [tempArray count] > 0) {
        [tempArray addObject:[filteredResults objectAtIndex:i]];
        [filteredResultsDict setValue:tempArray forKey:key];
    }
    else {
        [filtersArray addObject:[filteredResults objectAtIndex:i]];
        [filteredResultsDict setValue:filtersArray forKey:key];

    }
}

然后在我的实际for循环中,我可以调用它来代替前一个rowResults:

    NSNumber  *rowIDNum = [NSNumber numberWithInteger: [rowID integerValue]];
    rowResults = [[filteredResultsDict objectForKey:rowIDNum] valueForKey:@"value"];