Bhavin
Bhavin

Reputation: 27225

NSMutableDictionary from NSMutableArray using KVC

I have an Input Array of Dictionaries :

myArray = (
    {
        name:"abc";
        time:"6:00";
    },
    {
        name:"xyz";
        time:"7:00";
    },
    .
    .
)

I want Output Dictionary like this :

myDictionary = {
    "6:00":(
        {
            name:"abc";
            time:"6:00";
        },
        .
        .
     )
     "7:00":(
        {
            name:"xyz";
            time:"7:00";
        },
        .
        .
     )
}

What I tried :

I succeeded to get an array of distinct times using this line :

NSArray *arrTempKeys = [myArray valueForKeyPath:@"@distinctUnionOfObjects.Time"];

and then used the predicate inside for loop for arrTempKeys, to get all the dictionaries with same time value :

NSPredicate *pred = [NSPredicate predicateWithFormat:@"Date == %@",str];
NSArray *arrTemp = [myArray filteredArrayUsingPredicate:pred];

Finally, I assigned this arrTemp as an Object for the Key time and got the desired result.


What I want :

I know there are many other ways to get this output. But I just want to know if there is any single KVC coding line or any other optimum way available to do this thing.

Upvotes: 2

Views: 253

Answers (3)

Caleb
Caleb

Reputation: 124997

NSDictionary can do this with an assist from NSArray and KVC.

Try this:

NSDictionary *myDictionary = [NSMutableDictionary dictionaryWithObjects:myArray
                                                                forKeys:[myArray valueForKey:@"time"];

That should work, since NSArray's version of -valueForKey: returns an array of the values returned by each of it's elements for the key.

Caution: While the code above is concise and seems to solve your problem, it's not without some pitfalls. The main one is that a dictionary can only have one value for a given key, which means that if two or more of the entries in the array have the same value for the key @"time", only one of them (probably the last) will be represented in the resulting dictionary. Also, if any entry is missing a value for @"time", that entry will have [NSNull null] as its key. As above, if there are two or more missing the time value, only one will be represented in the dictionary.

Edit: Looking more closely at your question, I see that the times in the items are not necessarily distinct, so Hot Licks' answer will probably make more sense for you.

Upvotes: 3

Hot Licks
Hot Licks

Reputation: 47729

You want too much. Just write a simple loop. It will be the most efficient, clearest, and probably the most reliable solution:

NSMutableDictionary* myDict = [NSMutableDictionary dictionary];
for (NSDictionary* innerDict in myArray) {
    NSString* time = innerDict[@"time"];
    NSMutableArray* innerArray = myDict[time];
    if (innerArray == nil) {
        innerArray = [NSMutableArray array];
        [myDict setValue:innerArray forKey:time];
    }
    [innerArray addObject:innerDict];
}

Upvotes: 4

Wain
Wain

Reputation: 119031

No, there isn't. KVC allows you to navigate key paths, but it doesn't do collation of data in this way based on the content of key paths.

Upvotes: 0

Related Questions