2013-08-05 36 views
-4

我試圖找到裏面NSDictionarymyAr匹配的str標準的tags,我想有only那些確切的陣列不多也不少,結果正確篩選的NSArray。在這個例子中,我只想要myAr的第二個NSDictionary如何使用NSPredicate

雖然試圖通過使用謂詞來實現這一點,但是當我使用數組時總是返回空。

我想過濾使用數組,但這是行不通的。我想知道是否有人能告訴我我做錯了什麼,我怎麼能實現我的目標。在此先感謝

NSArray * myAr = @[ @{ @"tags": @[@"one",@"two",@"three"], 
          @"number": @"4" 
          }, 
         @{ @"tags": @[@"one",@"two"], 
          @"number":@"4" 
         }, 
         @{ @"tags": @[@"one",@"two",@"four"], 
          @"number":@"4" 
         }, 
         @{ @"tags": @[@"chacho",@"chocho"], 
          @"number":@"4" 
         }, 
         @{ @"tags": @[@"one"], 
          @"number":@"4" 
         } ]; 

    NSArray* str = @[@"one",@"two"]; 
    NSPredicate* pre = [NSPredicate predicateWithFormat:@"tags CONTAINS %@ ",str]; 
    myAr = [myAr filteredArrayUsingPredicate:pre]; 
    NSLog(@"%@",myAr); 
+0

以塊爲基礎的選手更方便,與他們你不會在同一siruation。 – holex

+1

我不太明白爲什麼這個問題如此嚴重低估。喬納森已經(幾乎)清楚地描述了他想要的內容,並提供了一些完整的獨立示例代碼。 - 我不明白爲什麼一些答案是downvoted ... –

+0

請不要[刪除並立即轉貼](http://stackoverflow.com/questions/18067919/how-to-filter-content-in-nsarray - 使用謂詞)。改爲編輯原件。 –

回答

4

如果我正確理解你的問題,你只需要更換「包含」由「=」 在謂詞:

[NSPredicate predicateWithFormat:@"tags = %@ ",str] 

這得到所有字典的陣列,其中的「標籤」的值等於 給定陣列str。在你的例子中,它僅返回一個包含第二個字典 的數組。

UPDATE:要查找所有字典裏的「標籤」值與 給出元素的數組,但獨立順序,以下略多 複雜謂語應該工作:

[NSPredicate predicateWithFormat:@"[email protected] = %d AND SUBQUERY(tags, $t, $t in %@)[email protected] = %d", 
    [str count], str, [str count]]; 

更新2:那是太複雜了,下面的斷言似乎還有工作:

[NSPredicate predicateWithFormat:@"[email protected] = %d AND ALL tags in %@", 
    [str count], str] 

(我假設str只包含不同元素。)

+0

感謝您的幫助。然而,我不能像這樣直接比較數組的順序,我的變化。如果那麼我的數組是'@ [@「two」,@「one」];'它不會找到它。這就是爲什麼我雖然使用'包含' –

+0

@JonathanThurft:好的,將盡快更新答案... –

+0

也我的數組標準是動態的,因此有時會有1,2或更多的項目,將對比 –

-1

蠻力的方式來做到這一點是刪除你的謂語,只是列舉:

NSArray *required = @[@"one", @"two"]; 
NSMutableArray *matches = [@[] mutableCopy]; 
[myAr enumerateObjectsUsingBlock:^(NSDictionary *dict, NSUInteger idx, BOOL *stop) { 
    [dict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { 
    if ([obj isKindOfClass:[NSArray class]]) { 
     BOOL match = YES; 
     for (NSString *item in required) { 
     if (![obj containsObject:item]) { 
      match = NO; 
      break; 
     } 
     } 
     if (match && [(NSArray *)obj count] == required.count) { 
     [matches addObject:obj]; 
     } 
    } 
    }]; 
}]; 
+0

這將返回與該條件相匹配的所有匹配,而不是僅具有這兩個條件的對象,它也將僅返回那些僅具有其中一個的項目。這些標準也會動態變化。 –

+0

您的原始問題使用了關鍵字「CONTAINS」,意思就是 - 包含「one」和「two」,這很讓人困惑。我已經更新了我的答案。更新我的答案以符合您的需求。 – garrettmurray

+0

@ MartinR的回答對於使用謂詞是堅實的,儘管我更新的蠻力方法現在也可以工作。 – garrettmurray

1

對於既不使用一個for循環,也沒有謂語格式字符串的回答,請嘗試使用塊,並利用NSSet中,以確定是否設定的你想匹配的標籤等於一組數組元素的標籤。例如:

NSSet* desiredTags = [NSSet setWithObjects:@"one", @"two", nil]; 

NSPredicate *tagFilterPredicate = [NSPredicate 
    predicateWithBlock:^BOOL (id data, NSDictionary *bindings) { 
     NSSet *tags = [NSSet setWithArray:[data objectForKey:@"tags"]]; 
     return [desiredTags isEqual:tags]; 
    }]; 

NSArray *resultArray = [myArr filteredArrayUsingPredicate:tagFilterPredicate]; 

記住,這確實分配每個迭代一組。所以,如果你想避免分配,這是不夠的。否則,它至少會避免一個格式字符串。

+0

是的,這也適用。 (我認爲'tags &&'檢查並不是真的需要。) –

+0

Woops - 這個'tags &&'檢查來自我正在起草的早期版本。 – nil