1

I have a data class:

@interface Car : NSObject
{
  Engine *_engine;
}
//...

With the class:

@interface Engine : NSObject
{
  NSInteger _power;
  NSString *_name;
}
//...

And an array:

NSArray *myArray = [ // a bunch of Car objects with Engines

How would I make a new array that contains all unique items based on Engine 'power'?

For Example:

0 Car with Engine ( power = 20, name = "engine one" )

1 Car with Engine ( power = 45, name = "engine two" )

2 Car with Engine ( power = 20, name = "engine three" )

Final array would be car objects 0 and 1

Both data classes have accessors, e.g:

- (NSInteger)power;

2 Answers 2

2
NSArray *cars = ...;
NSMutableDictionary *carsByUniqueEnginePowers = [NSMutableDictionary dictionary];
for (Car *car in cars) {
    NSNumber *enginePower = [NSNumber numberWithInteger:car.engine.power];
    [carsByUniqueEnginePowers setObject:car forKey:enginePower];
}
NSArray *carsWithUniqueEnginePowers = [carsByUniqueEnginePowers allValues];

Will pick the last item per engine power.

To get the first one replace the line

[carsByUniqueEnginePowers setObject:car forKey:enginePower];

with this:

if (![carsByUniqueEnginePowers objectForKey:power]) {
    [carsByUniqueEnginePowers setObject:car forKey:enginePower];
}
6
  • Try it in a moment...order doesn't really matter as long as it's unique Commented Nov 15, 2011 at 0:12
  • @Javy: Updated answer to cover "first occurences". Commented Nov 15, 2011 at 0:16
  • This seems to sort through an engine array, but I have an array of car objects that have engine objects with a power property...so this would only sort an array of engine objects, correct? Commented Nov 15, 2011 at 0:21
  • Oh, sorry, misread your question then. Updated answer. Should fit your needs now. Commented Nov 15, 2011 at 0:25
  • Yeah, perfect...I'm definitely going to look into those methods some more. Thanks a bunch. Commented Nov 15, 2011 at 0:32
1

Enumerate the array, building up a list of indices whose objects have previously-unseen power values.

Create a set to hold the already-seen powers; -[NSArray indexesOfObjectsPassingTest:] handles building the index list. Then ask the original array for its objectsAtIndexes:.

NSMutableSet * powerSet = [NSMutableSet set];
NSIndexSet * indexes;
indexes = [carArr indexesOfObjectsPassingTest:^BOOL(id car, NSUInteger idx, BOOL *stop) {
                  // valueForKey: will return an NSNumber instance for scalar values.        
                  NSNumber * powerNum = [[car engine] valueForKey:@"power"];
                  // This power is already in the set; pass over this car.
                  if( [powerSet containsObject:powerNum] ){
                      return NO;
                  }
                  // Add the new power to the set and include this car in the index set.        
                  else {
                      [powerSet addObject:powerNum];
                      return YES;
                  }
              }];
NSArray * uniqueEnginePowerCars = [carArr objectsAtIndexes:indexes];
1
  • Thanks for the help but Regexident's code was what I used. Thanks for the help. Commented Nov 15, 2011 at 0:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.