如何过滤一个包含NSDictionary和NSArray的数组?

6
我有一个包含多个NSDictionaries的数组,其中包括以下键:
  • NSString *name
  • NSString *ID
  • NSDictionary *phoneNumbersDict
现在我想要筛选出这个数组中具有phoneNumbersDict键为@"keyIAmLookingFor"且值为@"valueIAmLookingFor"的那个。
NSMutableArray *addressBookPhoneIndividuals = [NSMutableArray array];
for (int i = 0; i < x; i++) {
    [addressBookPhoneIndividuals addObject:@{
        @"name" : @"...",
        @"ID" : @"...",
        @"phoneNumbers" : @{...}
    }];
}
4个回答

6
NSString *keyIAmLookingFor = @"work";
NSString *valueIAmLookingFor = @"444-567-9019";

NSArray *addressBookPhoneIndividuals = @[
    @{
        @"name" : @"Mike Rowe",
        @"ID" : @"134",
        @"phoneNumbers" : @{
            @"work" : @"123-456-8000",
            @"school" : @"647-5543",
            @"home" : @"123-544-3321",
        }
    },
    @{
        @"name" : @"Eric Johnson",
        @"ID" : @"1867",
        @"phoneNumbers" : @{
            @"work" : @"444-567-9019",
            @"other" : @"143-555-6655",
        }
    },
    @{
        @"name" : @"Robot Nixon",
        @"ID" : @"-12",
        @"phoneNumbers" : @{
            @"work" : @"123-544-3321",
            @"school" : @"123-456-8000",
            @"home" : @"444-567-9019",
        }
    },
];

NSString *keyPath = [@"phoneNumbers." stringByAppendingString:keyIAmLookingFor];

NSPredicate *predicate =
[NSComparisonPredicate predicateWithLeftExpression:[NSExpression expressionForKeyPath:keyPath]
                                   rightExpression:[NSExpression expressionForConstantValue:valueIAmLookingFor]
                                          modifier:NSDirectPredicateModifier
                                              type:NSEqualToPredicateOperatorType
                                           options:0];

NSArray *result = [addressBookPhoneIndividuals filteredArrayUsingPredicate:predicate];

这将返回一个包含“Eric Johnson”字典的数组。
在进行任何复杂匹配时,我喜欢推荐使用NSComparisonPredicate。查看修改器、类型和选项的选项。里面有一些很好的内置匹配引擎,包括正则表达式和不区分大小写。无论如何,在这里可能并不必要,所以你可以替换为以下内容:
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%K = %@", keyPath, valueIAmLookingFor];

如果您只关心第一个结果,可以完全跳过keyPath/predicate这些操作:
for (NSDictionary *individualDict in addressBookPhoneIndividuals) {
    NSDictionary *phoneNumbers = [individualDict objectForKey:@"phoneNumbers"];
    NSString *possibleMatch = [phoneNumbers objectForKey:keyIAmLookingFor];
    if ([possibleMatch isEqualToString:valueIAmLookingFor]) {
        return individualDict;
    }
}

return nil;

很棒的答案!我一会儿就试试。如果我知道我要找的结果是唯一的(只返回一个对象),有没有其他方法可以替代filteredArray... - Peter Warbo
编辑:糟糕,我会将这部分内容添加到答案中以便更好地格式化。 - Sterling Archer
很好的回答。我的应用程序响应数据格式类似于这样,除了@"work"或@"school"或@"home"是另一个字典。有没有办法过滤掉搜索项的字典? @"work" : @{@"0":@"123-456-8000", @"1":@"123-456-8120", @"2":@"142-451-4574", } - Nassif

5
您可以使用NSPredicate来过滤您的数组。类似以下内容:
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"phoneNumbers.keyIAmLookingFor == %@", @"valueIAmLookingFor"];
NSArray *matches = [addressBookPhoneIndividuals filteredArrayUsingPredicate:predicate];

1

我不太明白你想如何过滤数组,但我经常使用的一种简单方法是基于块的过滤:

NSIndexSet* filteredIndexes = [addressBookPhoneIndividuals indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop){
    NSString *name = [obj objectForKey:@"name"];
    NSString *ID = [obj objectForKey:@"ID"];
    NSDictionary *phoneNumbersDict = [obj objectForKey:@"phoneNumbersDict"];

    return [[phoneNumbersDict objectForKey:@"keyIAmLookingFor"] isEqualToString:@"valueIAmLookingFor"];
}];

NSArray* filteredArray = [addressBookPhoneIndividuals objectsAtIndexes:filteredIndexes];

这有帮助吗?


0

你可以使用

i.     –allKeysForObject:
ii.    –objectForKey:
iii.   –valueForKey:
iv.    –keysOfEntriesPassingTest:
v.     –keysOfEntriesWithOptions:passingTest:

你也可以选择使用 NSPredicateFilter。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接