使用NSPredicate将阵列与另一个阵列进行比较

时间:2012-03-22 12:33:16

标签: iphone objective-c ios nspredicate

我有以下结构:

TxnSummary * t1 = [[TxnSummary alloc] init];
t1.txnId = @"1";
t1.shortDesc = @"First one";
t1.filters = [[NSArray alloc] initWithObjects:@"F1", @"F2", nil];

TxnSummary * t2 = [[TxnSummary alloc] init];
t2.txnId = @"2";
t2.shortDesc = @"Second one";
t2.filters = [[NSArray alloc] initWithObjects:@"F1",@"F2", @"F3", nil];

TxnSummary * t3 = [[TxnSummary alloc] init];
t3.txnId = @"3";
t3.shortDesc = @"Third one";
t3.filters = [[NSArray alloc] initWithObjects:@"F1", @"F3", nil];

TxnSummary * t4 = [[TxnSummary alloc] init];
t4.txnId = @"4";
t4.shortDesc = @"Fourth one";
t4.filters = [[NSArray alloc] initWithObjects:@"F4", nil];

NSArray * xnArray = [[NSArray alloc] initWithObjects:t1,t2,t3,t4, nil];

现在,如果我想找出哪些txn摘要有过滤器F1,那么我可以这样做:

NSPredicate * predicate = [NSPredicate predicateWithFormat:@"filters CONTAINS[cd] %@", @"F1"];
NSArray * filteredArray = [xnArray filteredArrayUsingPredicate:predicate];

如果我只比较一个字符串,这很有效,但是如果想知道哪些txn摘要都有过滤器“F1”或“F2”,那么如果我必须按照上述机制我会有创建两个谓词 - 每个谓词用于F1和F2,然后针对xnArray运行它(这看起来效率很低)。我希望能够创建一个过滤器字符串列表,并使用它来从xn数组中获取匹配的tx。

NSArray * filterStrings = [[NSArray alloc] initWithObjects:@"F1",@"F2", nil];

NSPredicate是否具有实现此目的的功能,还是应该使用其他一些过滤方法?

感谢您的帮助。

谢谢Kumar

4 个答案:

答案 0 :(得分:4)

如果我理解正确,您可以通过从谓词数组创建复合谓词来实现此目的,例如:

 NSPredicate *newFilterPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:selectedItemIDs];

编辑:添加了更详细的解释:

复合谓词将谓词组合成一个谓词。例如,如果要筛选包含“F1”或“F2”的项目,请执行以下操作:

// Normally build this in some kind of loop
NSPredicate *firstPredicate = [NSPredicate predicateWithFormat:@"filter =%@", @"F1"];
NSPredicate *secondPredicate = [NSPredicate predicateWithFormat:@"filter =%@", @"F1"];

// Create the array of predicates
NSArray *arrayOfPredicates = [NSArray arrayWithObjects:firstPredicate, secondPredicate, nil];

// Create the compound predicate
NSPredicate = [NSCompoundPredicate orPredicateWithSubpredicates:arrayOfPredicates];

还有“and”而不是“or”以及其他布尔条件的方法。完整的参考资料可以在这里找到:NSCompoundPredicate Class Reference

希望这有帮助,

戴夫

答案 1 :(得分:3)

您可以执行以下操作:

NSPredicate * predicate = [NSPredicate predicateWithFormat:@"filters CONTAINS[cd] %@ || filters CONTAINS[cd] %@", @"F1", @"F4"];

如果要添加数组中的所有键,可以执行以下操作:

NSArray * filterStrings = [[NSArray alloc] initWithObjects:@"F1",@"F4", nil];

NSString* predicateString = [filterStrings componentsJoinedByString:@"'|| filters CONTAINS[cd] '"];
predicateString = [NSString stringWithFormat:@"filters CONTAINS[cd] '%@'",predicateString];


NSPredicate * predicate = [NSPredicate predicateWithFormat:predicateString];
NSArray * filteredArray = [xnArray filteredArrayUsingPredicate:predicate];

答案 2 :(得分:1)

我不会使用NSArray来存储过滤器。这是使用NSSet/NSMutableSet代替的完美书籍示例。您可以与数组类似地进行初始化:

t1.filters = [[NSSet alloc] initWithObjects:@"F1", @"F2", nil];

然后,只需调用:

即可检查特定字符串是否存在
BOOL contains = [t1.filter containsObject:@"F1"];

您现在还可以使用filteredSetUsingPredicateobjectsPassingTest等方法过滤该集合(与块一起使用),甚至可以与其他集合创建交叉点或联合(isSubsetOfSet,{{1}等等)。因此,例如,您可以使用搜索的元素创建一个新集合,并检查集合是否包含它们:

intersectsSet

搜索集合比数组快得多,因为set由Hash table备份,而数组必须线性搜索。

答案 3 :(得分:0)

如果完全匹配是正确的,您可以使用IN谓词,如下所示:

NSArray *filterStrings = [NSArray arrayWithObjects:@"F1", @"F2", nil];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"filters IN %@", filterStrings];

NSArray *filteredArray = [xnArray filteredArrayUsingPredicate:predicate];