LoginSignup
3
3

More than 5 years have passed since last update.

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

Last updated at Posted at 2015-06-22

はじめに

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

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

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

使い方

    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から該当の項目を見つける

単一の結果を返す(複数該当した場合、先頭の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];
}
複数の結果を返す

+ (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];
}

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

ソート

+ (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"から始まる文字列か空文字指定で昇順指定に、それ以外では降順指定にしています。

おわりに

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

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3