2011-01-28 68 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