2012-03-22 3 views
1

Я следующую структуру:Сравнивая массив с другой, используя 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 (что кажется неэффективным). Я хочу иметь возможность создавать список строк фильтров и использовать их для извлечения соответствующих txs из массива xn.

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

Имеет ли NSPredicate функциональность для достижения этой цели или следует использовать какой-либо другой метод фильтрации?

Цените свою помощь.

Спасибо, Kumar

ответ

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

Отлично. Спасибо за ваш вклад. – KumarM

0

Если точное соответствие ОК, вы могли бы использовать IN предикат как так:

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

NSArray *filteredArray = [xnArray filteredArrayUsingPredicate:predicate]; 
+0

Это соответствие OR. Например, xn 1 может содержать строки фильтра F1, F2 и xn2, которые могут содержать F2, F3, и, скажем, я хочу узнать все xns, у которых есть строки фильтров либо F1, либо F3, то оба xn 1 и xn 2 являются совпадением. – KumarM

4

Если я вас правильно понимаю, вы можете добиться этого путем создания составного предиката из массив предикатов, например:

NSPredicate *newFilterPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:selectedItemIDs]; 

EDIT: добавлено более подробное объяснение:

Комбинированные предикаты объединяют предикаты в один предикат. Например, если вы хотите, чтобы фильтр для элементов, содержащих «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]; 

Есть также методы «и» вместо «или», а также других логических условий. Полный справочник можно найти здесь: NSCompoundPredicate Class Reference

Надеется, что это помогает,

Dave

+0

Не могли бы вы уточнить? – KumarM

+0

Несомненно, добавит больше моего ответа –

+0

Спасибо за объяснение. Помог узнать новое о предикатах. Я попробовал это, и это работает как шарм. Считаете ли вы, что это более эффективно, чем решение, предоставленное ggrana ниже? – KumarM

1

я бы не использовать 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]; 

Поиска набора гораздо быстрее, чем массив, потому что набор подкрепленные Hash table, в то время как массив имеет для поиска линейно.

Смежные вопросы