Anuj Rajput
Anuj Rajput

Reputation: 844

Create an array of NSSet having values of distinct properties of an object present in another NSArray

I have an array having objects with different properties. I want to create an array of sets which contain objects with same value of a single property of the object.

Suppose this is an array of object which has property a and b

1: {a:10, b:5}, 2: {a:2,b:5}, 3: {a:20,b:5}, 4: {a:5,b:5}, 5: {a:4,b:20}, 6: {a:51,b:20}

I want to create another array of NSSet of objects with distinct values of property b

so the result would be the following Array of 2 NSSet

1: {a:10, b:5}, {a:2,b:5}, {a:20,b:5}, {a:5,b:5}

2: {a:4,b:20}, {a:51,b:20}

How can this be done?

Upvotes: 0

Views: 549

Answers (3)

Nikhil Lihla
Nikhil Lihla

Reputation: 613

Using Key-Value coding collection operators, we can get the array of distinct values for an object. Then you could easily compute the results you want.

In your case this could be done like this.

    NSArray *arrayOfDistinctObjects = [array valueForKeyPath:@"@distinctUnionOfObjects.b"];
    NSMutableArray *newSetArray     = [NSMutableArray new];

    for (id value in arrayOfDistinctObjects) {
        NSPredicate *predicate  = [NSPredicate predicateWithFormat:@"SELF.b == %@", value];
        NSArray *filterArray    = [array filteredArrayUsingPredicate:predicate];
        NSSet   *newSet         = [NSSet setWithArray:filterArray];
        [newSetArray addObject:newSet];
    } 

where array is the array of objects on which you wanna operate. arrayOfDistinctObjects gives you the array of distinct values for b.

Upvotes: 1

Abhinav
Abhinav

Reputation: 38162

This is how you can do this:

NSArray *data = @[@{@"a":@10, @"b":@5}, @{@"a":@2,@"b":@5}, @{@"a":@4,@"b":@20}, @{@"a":@51,@"b":@20}];
NSSet *bSet = [NSSet setWithArray: [data valueForKey: @"b"]];

NSMutableArray *filteredArray = [[NSMutableArray alloc] initWithCapacity: bSet.count];

for (NSNumber *bValue in bSet) {
    NSPredicate *anArrayFilterPredicate = [NSPredicate predicateWithBlock:^BOOL(NSDictionary *aDictionaryData, NSDictionary *bindings) {
        if ([aDictionaryData[@"b"] isEqual:bValue]) {
            return YES;
        }

        return NO;
    }];

    NSArray *uniqueBValueArray = [data filteredArrayUsingPredicate:anArrayFilterPredicate];

    [filteredArray addObject:uniqueBValueArray];
}

NSLog(@"filteredArray = %@", filteredArray);

Upvotes: 1

rmaddy
rmaddy

Reputation: 318794

I'd do this by first creating a dictionary of sets where the keys of the dictionary are the unique values of "b".

Note: This is untested code. There could be typos here.

NSArray *objectArray = ... // The array of "SomeObject" with the "a" and "b" values;
NSMutableDictionary *data = [NSMutableDictionary dictionary];
for (SomeObject *object in objectArray) {
    id b = object.b;
    NSMutableSet *bSet = data[b];
    if (!bSet) {
        bSet = [NSMutableSet set];
        data[b] = bSet;
    }

    [bSet addObject:object];
}

NSArray *setArray = [data allValues];

setArray will contain your array of sets.

This codes also assumes you have a sane isEqual: and hash implementation on your SomeObject class.

Upvotes: 2

Related Questions