我有以下结构:
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"];
现在,您还可以使用filteredSetUsingPredicate
、objectsPassingTest
(用于块)等方法过滤集合,甚至可以创建与其他集合(isSubsetOfSet
、intersectsSet
等)的交集或并集。例如,您可以用搜索到的元素创建一个新的集合,并检查该集合是否包含它们:
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];