Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Grouping NSArray of NSDictionary based on a key in NSDictionay

I am trying to filter out a NSArray of NSDictionaries. With my below example, I want dict1, dict2 & dict4 grouped in one array, dict3 & dict5 grouped in second array and dict6 in third array.

I am getting this data in NSArray, so essentially the "orig" array below is my input and I know that I need to do grouping based on "Name" key.

Instead of looping through the NSArray I though of using valueForKeyPath to return me array based on the key path but this does not work (crashes with logs -[NSMutableArray addObjectsFromArray:]: array argument is not an NSArray').

Any suggestion.

NSDictionary *dict1 = @{@"Name" : @"T1", @"Age" : @"25"};
NSDictionary *dict2 = @{@"Name" : @"T1", @"Age" : @"25"};
NSDictionary *dict3 = @{@"Name" : @"T2", @"Age" : @"27"};
NSDictionary *dict4 = @{@"Name" : @"T1", @"Age" : @"25"};
NSDictionary *dict5 = @{@"Name" : @"T2", @"Age" : @"27"};
NSDictionary *dict6 = @{@"Name" : @"T3", @"Age" : @"28"};

NSArray *orig = @[dict1, dict2, dict3, dict4, dict5, dict6];

NSMutableArray *final = [NSMutableArray array];

final = [orig valueForKeyPath:@"@unionOfArrays.Name"];

NSLog(@"Final = %@", final);
like image 721
Abhinav Avatar asked Jan 04 '14 19:01

Abhinav


People also ask

Is Nsarray ordered?

The answer is yes, the order of the elements of an array will be maintained - because an array is an ordered collection of items, just like a string is an ordered sequence of characters...

What is the difference between NSDictionary and NSMutableDictionary?

Main Difference is:NSMutableDictionary is derived from NSDictionary, it has all the methods of NSDictionary. NSMutableDictionary is mutable( can be modified) but NSDictionary is immutable (can not be modified).

Can Nsarray contain nil?

arrays can't contain nil.

How do I create an NSDictionary in Objective C?

Creating NSDictionary Objects Using Dictionary Literals In addition to the provided initializers, such as init(objects:forKeys:) , you can create an NSDictionary object using a dictionary literal. In Objective-C, the compiler generates code that makes an underlying call to the init(objects:forKeys:count:) method.


2 Answers

It's a little hard to tell if what you want is three different arrays where each one only contains entries with a specific Name value (as your first paragraph suggests) or if you want a single array where the entries are sorted by Name (as your second paragraph suggests). Regardless,

To sort orig by the value of the Name field:

NSArray *sortedByName = [orig sortedArrayUsingDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"Name" ascending:YES]]];

To get a new array by selecting only entries with a specific value for Name:

NSArray *t1Only = [orig filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"Name = %@", @"T1"]];
like image 51
Tom Harrington Avatar answered Oct 05 '22 06:10

Tom Harrington


If the desired output is an array of arrays, you can get there by building a dictionary keyed by the name attribute in the orig dictionaries:

- (NSArray *)collateByName:(NSArray *)original {

    NSMutableDictionary *collate  = [NSMutableDictionary dictionary];
    for (NSDictionary *d in original) {
        NSString *newKey = d[@"Name"];
        NSMutableArray *newValue = collate[newKey];
        if (!newValue) {
            newValue = [NSMutableArray array];
            collate[newKey] = newValue;
        }
        [newValue addObject:d];
    }
    return [collate allValues];
}

It's a little verbose, but clear, I think. If you want to decide the attribute to distinguish with programmatically, pass in another param called attribute and replace the literal @"Name" with it.

like image 23
danh Avatar answered Oct 05 '22 07:10

danh