我有一个数组,包含170k个字符串(字典中的单词(和一个字符串,看起来像"glapplega"。我正试图从字符串中提取单词"apple"(其中"apple"是数组中的一个单词(。我还需要确保提取的单词至少有3个字符。我现在的代码如下:
NSPredicate *wordPredicate = [NSPredicate predicateWithFormat:@"'%@' contains[cd] SELF", string];
NSPredicate *lengthPredicate = [NSPredicate predicateWithFormat:@"SELF.length > 2"];
NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[wordPredicate, lengthPredicate]];
return [_words filteredArrayUsingPredicate:lengthPredicate];
长度谓词独立工作,但单词谓词不工作(它返回一个空数组,尽管"apple"是数组中的一个单词(。
我怀疑在谓词中使用SELF作为右表达式可能有问题,因为我发现的所有示例都将其作为左表达式,尽管我无法证实这一点。
编辑:我知道这可能可以通过regexs(如本文所述(来实现,但我希望有办法解决这个问题,因为regexs在如此大的数据集中可能会很慢。
如果您自己使用块谓词迭代数组,那么解决这个问题很容易。在某种程度上,格式化的NSPredcate必须归结为这一点,因此不应该对性能造成太大影响。-[NSString rangeOfString:]
可用于测试是否包含字符串。
return [_words filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL (id evaluatedString, NSDictionary *bindings) {
return string.length > 2 && [string rangeOfString:evaluatedString].location != NSNotFound;
}]];
您知道上面的假设和谓词是完全有效的。你唯一做错的就是引用。重新格式化你的谓词并使其像这样,
NSArray * array = @[@"Apple", @"lega", @"foo", @"bar"];
NSString *string = @"glapplega";
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%@ contains[cd] SELF and SELF.length > 2", string];
NSLog(@"%@",[array filteredArrayUsingPredicate:predicate]);
(
Apple,
lega
)
指定格式并将字符串提供给该格式时,谓词会自行放置引号。所以,你在这里搞错了。
#define rchar (rand() % ('z'-'a') + 'a')
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
NSMutableArray * mar = [NSMutableArray new];
for (int i = 0; i<170000; i++)
{
NSString * str = [NSString stringWithFormat:@"%c%c%c%c",rchar, rchar, rchar, rchar];
[mar addObject:str];
}
NSString * bigStr = @"asdfghjkl;loiuytrdcvcdrtgvfrtghvcftyghvfghcfdtyjghvncdfjtygmvcnfhjghjkgfhdgsxgrecrvtbkunhlmnhubkujvytchrtxgrecdjvbyhnkbjgcfhvyjhbghnkbjchgdfvbghnukbytvjycterwxrzewxcevfbjnkmjohgytreytwexkutckhtdtcfhvjgkjmhgcjhewwzsserdp9dlkuydssqwsxdchvggjhmgbj";
NSDate *start = [NSDate date];
NSArray * marFiltered = [mar filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
return [bigStr rangeOfString:evaluatedObject].length>2;
}]];
NSLog(@"found %lu items in %f seconds", (unsigned long)[marFiltered count], -[start timeIntervalSinceNow]);
}
输出:
2014-05-11 09:09:53.048 170k[89396:303] found 85 items in 0.542431 seconds
您可以尝试两个选项来定义谓词。一个格式字符串和一个块。下面是一段演示这两者的代码。我和他们都打过球,可以分享他们的表现是一样的。我只有耐心在最大值为INT32_max/2(很多项目(的情况下运行它。
给。希望这能澄清并有所帮助:
NSString* searchString = @"AB0";
NSUInteger capacity = 1000000;
NSMutableArray* array = [NSMutableArray array];
NSLog(@"Fillling array with %lu UUIDS. Be patient.", (unsigned long)capacity);
NSUInteger batch = 0;
for ( NSUInteger i = 0; i < capacity; i++ ) {
[array setObject:[[NSUUID UUID] UUIDString] atIndexedSubscript:i];
if (i != 0 && i % (capacity / 10) == 0 ) {
NSLog(@"Completed %lu%%", (unsigned long)++batch * 10);
}
}
NSLog(@"Done.");
NSPredicate* formatPredicate = [NSPredicate predicateWithFormat:@"SELF contains[cd] %@ AND SELF.length > 3", searchString];
NSLog(@"Filtering with predicate: %@", formatPredicate);
NSArray* formatArray = [array filteredArrayUsingPredicate:formatPredicate];
NSLog(@"Got %lu results.", formatArray.count);
NSPredicate* blockPredicate = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
NSString* theString = evaluatedObject;
return theString.length > 3 && [theString rangeOfString:searchString].location != NSNotFound;
}];
NSLog(@"Filtering with predicate: %@", blockPredicate);
NSArray* blockArray = [array filteredArrayUsingPredicate:blockPredicate];
NSLog(@"Got %lu results.", blockArray.count);
附言:如果你使用的是大数字行INT32_MAX:(