NSDictionaryのリストから該当項目取り出し、ソート

# はじめに
ディクショナリをリストに入れて保持しておく場面があると思います。

そのリストに対して以下を行いたい時のための処理です。
　・あるキーに該当の値を持つディクショナリを取り出す
　・あるキーに該当の値を持つディクショナリをすべて取り出す
　・単一又は複数条件でのソート

この処理を使う場面が多いので自分メモ用に残しています。

# 使い方

```objc:
    NSMutableArray *dummyArray = [NSMutableArray array];
    
    [dummyArray addObject:@{@"name":@"Tanaka", @"age":@"30"}];
    [dummyArray addObject:@{@"name":@"Suzuki", @"age":@"40"}];
    [dummyArray addObject:@{@"name":@"Yamada", @"age":@"30"}];

    // 単一の項目
    NSDictionary *dic = [Util findObjectFromDictionaryArray:dummyArray keyAndValues:@[@{@"name":@"Suzuki"}]];
    NSLog(@"%@", [dic description]);
//    { age = 40; name = Suzuki; }

    
    // 複数の項目
    NSArray *filteredArray = [Util findObjectsFromDictionaryArray:dummyArray keyAndValues:@[@{@"age":@"30"}]];
    NSLog(@"%@", [filteredArray description]);
//    (
//     {age = 30; name = Tanaka; },
//     {age = 30; name = Yamada; }
//    )

    // ソート
    NSArray *sortKeyAndOrders = @[@{@"age":@""}, @{@"name":@"DESC"}];
    NSArray *sortedArray = [Util sortDictionaryArray:dummyArray sortKeyAndOrders:sortKeyAndOrders];
    NSLog(@"%@", [sortedArray description]);
//    (
//     {age = 30; name = Yamada; },
//     {age = 30; name = Tanaka; },
//     {age = 40; name = Suzuki; }
//    )

```


# NSDictionaryのArrayから該当の項目を見つける

```objc:単一の結果を返す(複数該当した場合、先頭の1件)

+ (NSMutableDictionary *)findObjectFromDictionaryArray:(NSArray *)sourceArray keyAndValues:(NSArray *)keyAndValues
{
    if (!sourceArray || [sourceArray count] == 0) {
        return nil;
    }
    
    if (!keyAndValues) {
        return nil;
    }
    
    if (![sourceArray[0] isKindOfClass:[NSDictionary class]]) {
        return nil;
    }
    
    NSMutableArray *conditions = [NSMutableArray array];
    
    for (NSDictionary *keyAndValue in keyAndValues) {
        NSString *key = [keyAndValue allKeys][0];
        [conditions addObject:[NSPredicate predicateWithFormat:@"%K = %@", key, keyAndValue[key]]];
    }
    
    NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:conditions];
    
    NSArray *array = [sourceArray filteredArrayUsingPredicate:predicate];
    
    if (!array || [array count] == 0) {
        return nil;
    }
    
    return array[0];
}
```

```objc:複数の結果を返す

+ (NSArray *)findObjectsFromDictionaryArray:(NSArray *)sourceArray keyAndValues:(NSArray *)keyAndValues
{
    if (!sourceArray || [sourceArray count] == 0) {
        return nil;
    }
    
    if (!keyAndValues) {
        return nil;
    }
    
    if (![sourceArray[0] isKindOfClass:[NSDictionary class]]) {
        return nil;
    }
    
    NSMutableArray *conditions = [NSMutableArray array];
    
    for (NSDictionary *keyAndValue in keyAndValues) {
        NSString *key = [keyAndValue allKeys][0];
        [conditions addObject:[NSPredicate predicateWithFormat:@"%K = %@", key, keyAndValue[key]]];
    }
    
    NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:conditions];
    
    return [sourceArray filteredArrayUsingPredicate:predicate];
}
```

※ 単一、複数どちらも完全一致での判定です。

```objc:ソート

+ (NSArray *)sortDictionaryArray:(NSArray *)sourceArray sortKeyAndOrders:(NSArray *)sortKeyAndOrders
{
    NSMutableArray *sortDescriptors = [NSMutableArray array];
    
    for (NSDictionary *sortKeyAndOrder in sortKeyAndOrders) {
        
        NSString *key = [[sortKeyAndOrder allKeys] firstObject];
        NSString *value = [sortKeyAndOrder[key] lowercaseString];
        
        BOOL ascending = NO;
        if ([value length] == 0 || [value hasPrefix:@"asc"]) {
            ascending = YES;
        }
        
        NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:key ascending:ascending];
        [sortDescriptors addObject:sortDescriptor];
    }
    
    return [sourceArray sortedArrayUsingDescriptors:sortDescriptors];
}

```

※ ソート順を明示的に指定するために条件はarrayでの指定にしています。
"asc"から始まる文字列か空文字指定で昇順指定に、それ以外では降順指定にしています。

# おわりに
何かの参考になりましたら幸いです。