2011-01-28 102 views
1

我有一個plist,我已經定義爲包含許多數組的字典。我想從該字典中抽出所有具有與給定字符串匹配的第一個「Item 0」(默認命名約定)的數組。使用NSPredicate過濾數組的NSDictionary

我嘗試了一些類似於過濾NSArray的東西,但我得到了一個正則表達式錯誤,並且控制檯輸出了字典中第一個數組的內容。

此外,我是否需要實例化我的NSDictionary作爲NSMutableDictionary,因爲我將對它執行過濾器過程?將從plist讀入的NSDictionary複製到一個必需的NSDictionary然後完成它的工作是更好的形式嗎?

回答

9

這是可能的,但在一個迂迴的方式。我建議你考慮使用不同的方法。

話雖這麼說,這裏是你會怎麼做:

NSDictionary *d = [NSDictionary dictionaryWithObjectsAndKeys: 
        [NSArray arrayWithObjects:@"a", @"b", @"c", nil], @"a", 
        [NSArray arrayWithObjects:@"b", @"c", @"a", nil], @"b", 
        [NSArray arrayWithObjects:@"c", @"a", @"b", nil], @"c", 
        [NSArray arrayWithObjects:@"a", @"b", @"c", nil], @"d", 
        nil]; 
NSPredicate *p = [NSPredicate predicateWithFormat:@"%@[SELF][0] == 'a'", d]; 
NSLog(@"%@", p); 
NSArray *keys = [d allKeys]; 
NSArray *filteredKeys = [keys filteredArrayUsingPredicate:p]; 
NSLog(@"%@", filteredKeys); 
NSDictionary *matchingDictionary = [d dictionaryWithValuesForKeys:filteredKeys]; 
NSLog(@"%@", matchingDictionary); 

這裏是發生了什麼事情:

我們有我們的源字典,d。這是一個字典,其中一個字母(a,b,cd)被鍵入到一個數組中。我們將找到對應於第一個元素爲a的數組的所有

我們的謂語是:

[NSPredicate predicateWithFormat:@"%@[SELF][0] == 'a'", d]; 

這裏,我們使用的索引操作上我們的源代碼字典。 SELF,當評估該謂詞時,將是d密鑰中的一個。所以%@[SELF]將返回一個數組。然後我們取該數組的第0個元素,並將其與字符串a進行比較。如果匹配,則返回YES

然後,我們抓住字典中的所有鍵並使用此謂詞對它們進行過濾。這意味着結果數組將僅包含對應數組的第一個元素爲a的鍵。

一旦我們有了匹配的關鍵字,我們就從源字典中提取一個「子字典」來獲得最終的縮減字典。

在上面的試驗中,matchingDictionary具有兩個鍵(ad),它們都鍵合到含(a, b, c)陣列。

如果你想要一個NSArray而不是包含匹配的數組,你應該使用-[NSDictionary objectsForKeys:notFoundMarker:]來代替。

但是,這是一個尷尬的解決方案,我仍然認爲你應該重新組織你的數據。

2

我敢肯定你不能使用NSPredicate這裏(但如果你想在的NSDictionary你可以內對陣列使用NSPredicate)。然而,有一個完全可以接受的替代方案,通過下面的例子所示:

NSMutableArray* filteredArrays = [[NSMutableArray alloc] init]; 
for (NSString* currentKey in myDictionaryOfArrays) 
{ 
    NSArray* currentArray = [myDictionaryOfArrays objectForKey:currentKey]; 
    NSString* objectAtFirstIndex = [currentArray objectAtIndex:0]; 
    if ([objectAtFirstIndex isEqualTo:mySearchString]); 
    { 
     [filteredArrays addObject:currentArray]; 
    } 
} 

順便說一句,快速enumuration(「每個」)語句應該使用,因爲你可以從它的性能提升。

你剩下的是一個可變數組,符合你的搜索條件。如果你想要更整潔一些(例如,如果這段代碼構成一個方法),你可以把它轉換成一個不可變的數組(除非你想繼續進行修改)。

NSArray* filteredResults = [NSArray arrayWithArray:filteredArrays]; 
+0

大部分是正確的,除了在`for ... in`循環中使用字典時,最終會遍歷*鍵*而不是值。 – 2011-01-28 17:45:49

+0

我喜歡這個解決方案,但沒有看到這是如何「迭代鍵」。 NSString * objectAtFirstIndex = [currentArray objectAtIndex:0]; if([objectAtFirstIndex isEqualTo:mySearchString]); objectAtFirstIndex正在獲取當前數組的值而不是密鑰。正確? – Nungster 2011-01-28 19:03:33

相關問題