使用NSPredcate将一个数组与另一个数组进行比较



我有以下结构:

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数组中获取匹配的txs。

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

NSPredicate是否具有实现这一点的功能,或者我应该采用其他过滤方法?

感谢你的帮助。

谢谢,Kumar

您可以执行以下操作:

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];

如果我理解正确,您可以通过从谓词数组创建一个复合谓词来实现这一点,例如:

 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类引用

希望这能有所帮助,

Dave

我不会使用NSArray来存储过滤器。这是一个使用NSSet/NSMutableSet的完美例子。您可以类似于数组进行初始化:

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

然后,您只需调用即可检查该特定字符串是否存在

BOOL contains = [t1.filter containsObject:@"F1"];

现在,您还可以使用filteredSetUsingPredicateobjectsPassingTest(用于块)等方法过滤集合,甚至可以创建与其他集合(isSubsetOfSetintersectsSet等)的交集或并集。例如,您可以用搜索到的元素创建一个新的集合,并检查该集合是否包含它们:

NSSet* toFind = [[NSSet alloc] initWithObjects:@"F1", @"F3", nil];
[toFind isSubsetOfSet:t1.filters];

搜索集合比搜索数组快得多,因为集合是由哈希表备份的,而数组必须线性搜索。

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

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

相关内容

最新更新