Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free.

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;
share|improve this question

2 Answers 2

up vote 2 down vote accepted
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];
}
share|improve this answer
    
Try it in a moment...order doesn't really matter as long as it's unique –  TigerCoding Nov 15 '11 at 0:12
    
@Javy: Updated answer to cover "first occurences". –  Regexident Nov 15 '11 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? –  TigerCoding Nov 15 '11 at 0:21
    
Oh, sorry, misread your question then. Updated answer. Should fit your needs now. –  Regexident Nov 15 '11 at 0:25
    
Yeah, perfect...I'm definitely going to look into those methods some more. Thanks a bunch. –  TigerCoding Nov 15 '11 at 0:32

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];
share|improve this answer
    
Thanks for the help but Regexident's code was what I used. Thanks for the help. –  TigerCoding Nov 15 '11 at 0:33
    
@Javy: Sure thing! –  Josh Caswell Nov 15 '11 at 0:33

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.