2

I want to get the Collection of a Specific Property from an array dictionary which has an array of values. Following is my array NSDictionaries:

NSArray *arrGroupsFromServer= @[
    @{@"Id": @"7d1021ba-e9be-40c1-a0a1-ad2a2d185b74",@"Name": @"1",@"modifiedDate": @"2016-01-29T15:39:57.000Z",@"PupilIdCollection":@[@"1",@"2"]},
    @{@"Id": @"4d830b79-f447-4ad7-8de1-063acf3e242c",@"Name": @"2 TEST",@"modifiedDate": @"2016-01-29T15:39:57.000Z",@"PupilIdCollection":@[@"1",@"3"]},
    @{@"Id": @"e481987d-fde8-4a6b-8e05-73877065236d",@"Name": @"CQ",@"modifiedDate": @"2016-01-29T15:39:57.000Z",@"PupilIdCollection":@[@"1",@"4"]},
    @{@"Id": @"1a44989d-8b3f-4d8e-8c74-a09c893ca02d",@"Name": @"Intervention group Number",@"modifiedDate": @"2016-01-29T15:39:57.000Z",@"PupilIdCollection":@[@"1",@"5"]},
    @{@"Id": @"f10f2fe0-b575-450d-ad63-10d0e8fbe097",@"Name": @"EYFS Caterpillars",@"modifiedDate": @"2016-01-29T15:39:57.000Z",@"PupilIdCollection":@[@"1",@"6"]},
    @{@"Id": @"232168c1-73a4-4bbb-b9a2-58e6765e4b2c",@"Name": @"Guided Reading group",@"modifiedDate": @"2016-01-29T15:39:57.000Z",@"PupilIdCollection":@[@"1",@"6"]},
    @{@"Id": @"1e9b66f7-c4a7-4774-b062-ce23f587a319",@"Name": @"HfL",@"modifiedDate": @"2016-01-29T15:39:57.000Z",@"PupilIdCollection":@[@"1",@"7"]},
    @{@"Id": @"62d53fc5-1fbf-4ebe-bc52-d07ec2680c66",@"Name": @"Red Intervention group",@"modifiedDate": @"2016-01-29T15:39:57.000Z",@"PupilIdCollection":@[@"1",@"8"]},
    @{@"Id": @"a70e7429-996a-46ff-aff7-1e1bc5e17c3b",@"Name": @"SEN Green group",@"modifiedDate": @"2016-01-29T15:39:57.000Z",@"PupilIdCollection":@[@"1",@"9"]},
    @{@"Id": @"44441c6f-843b-4933-9191-1f3afb23b6cf",@"Name": @"STAT",@"modifiedDate": @"2016-01-29T15:39:57.000Z",@"PupilIdCollection":@[@"1",@"2"]},
    @{@"Id": @"04aedc28-4706-49a1-8bbd-9d58179cfd55",@"Name": @"TIST",@"modifiedDate": @"2016-01-29T15:39:57.000Z",@"PupilIdCollection":@[@"1",@"2"]},
    @{@"Id": @"c98f592e-4adc-4d9d-a484-ae5b417f11db",@"Name": @"Year 8",@"modifiedDate": @"2016-01-29T15:39:57.000Z",@"PupilIdCollection":@[@"1",@"2"]}
];

Now I want to collect the PupilIdCollection Property into one single array with the DistintctUnion of all the values as follows:

NSArray * PupilIdCollection=@[@"1",@"2",@"3",@"4",@"5",@"6",@"7",@"8",@"9"];(e.g. Order doesn't matter)

I have tried it the following way:

NSArray *arrPupilsIdsFromServer = [arrGroupsFromServer valueForKeyPath:@"@distinctUnionOfObjects.PupilIdCollection"];

But this only gives me different Objects of PupilIdCollection in an array of arrPupilsIdsFromServer rather than the one object with the array of all the values in one array as following:

Screenshot

I want something like the following in just one line of code in KVC:

NSArray * PupilIdCollection=PupilIdCollection=@[@"1",@"2",@"3",@"4",@"5",@"6",@"7",@"8",@"9"];(e.g. Order doesn't matter);(e.g. Order doesn't matter)

How to do this?

honk
  • 9,137
  • 11
  • 75
  • 83
BhavikKama
  • 8,566
  • 12
  • 94
  • 164

3 Answers3

2

You need to use the @distinctUnionOfArrays instead of the @distinctUnionOfObjects. This operator helps flattening hierarchies of collections, and merge sub-arrays. See the developer documentation for details.

For example, these lines (used on your very NSArray)

NSArray *arrPupilsIdsFromServer = [arrGroupsFromServer valueForKeyPath:@"@distinctUnionOfArrays.PupilIdCollection"];
NSLog(@"\nPupil Ids From Server:%@", arrPupilsIdsFromServer);

Yield this output:

Pupil Ids From Server:(
1,
2,
3,
4,
5,
6,
7,
8,
9
)
Wain
  • 118,658
  • 15
  • 128
  • 151
Motti Shneor
  • 2,095
  • 1
  • 18
  • 24
0

from wain's answer you can do it after getting the values of PupilIdCollection for example,

 NSArray *pupilIdCollection = [arrGroupsFromServer valueForKeyPath:@"PupilIdCollection"];
__block  NSMutableSet *mutableSet = [[NSMutableSet alloc] init];
 [pupilIdCollection enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
    [mutableSet addObjectsFromArray:obj];
 }];
 pupilIdCollection = [mutableSet allObjects];
 NSLog(@"all objects-%@",pupilIdCollection);
Shankar BS
  • 8,394
  • 6
  • 41
  • 53
  • written nicely and efficiently (even though there's no need for it - there is a KVC collection operator that does the work) however - the enumerateObjectsUsingBlock: method runs concurrently on the subarrays, and calls mutableSet AddObjectsFromArray: from several threads at once. As far as I know - NSMutableSet is NOT thread-safe, and you should better synchronise the assignments to the set. – Motti Shneor Oct 26 '20 at 10:34
-1

Wain has explained it very well. I too feel that it would be very difficult to achieve in a single line. You can create a single array for all those elements and then use distinctUnionOfObjects.

NSMutableArray *singleArray =[NSMutableArray array];
for (NSDictionary *d in arrGroupsFromServer) {
    [singleArray addObjectsFromArray:[d objectForKey:@"PupilIdCollection"]];
}
NSArray *pupilIdCollection = [singleArray valueForKeyPath:@"@distinctUnionOfObjects.self"];
san
  • 3,350
  • 1
  • 28
  • 40