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);
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...
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).
arrays can't contain nil.
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.
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"]];
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With