2012-03-22 81 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運行它(這看起來效率很低)。我希望能夠創建一個過濾器字符串列表,並使用它從xn數組中獲取匹配的txs。

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

NSPredicate是否具有實現這一功能的功能,還是應該使用其他方法進行過濾?

感謝您的幫助。

感謝,庫馬爾

回答

3

你可以做這樣的事情

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 2012-03-27 13:21:56

0

如果精確匹配OK,你可以使用IN謂詞像這樣:

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

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

這是一個或匹配。例如,xn 1可以包含過濾器字符串F1,F2,而xn 2可以包含F2,F3,假設我想要找出所有具有過濾器字符串F1或F3的xns,則xn 1和xn 2都匹配。 – KumarM 2012-03-22 12:58:36

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

也有對的「和」,而不是「或」以及其他布爾條件的方法。完整的參考可以在這裏找到:NSCompoundPredicate Class Reference

希望這有助於

戴夫

+0

你能否詳細說明一下? – KumarM 2012-03-22 12:57:23

+0

當然會增加更多我的回答 – 2012-03-22 13:25:58

+0

感謝您的解釋。幫助學習有關謂詞的新事物。我試過這個,它的功能就像一個魅力。你認爲比下面ggrana提供的解決方案更有效嗎? – KumarM 2012-03-27 13:25:20

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備份更快,而一個數組線性搜索。如果您要添加的所有是一個數組中的鍵,你可以做這樣的事情

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