开发者

Putting single attribute from group of entity objects into an array

If I have an NSArray of custom objects (in this case Core Data objects), how would I put all the items of a particular attribute in another NSArray. Is there a way I can use blocks?

For instance, if the class is People, and one of the attributes is age, and there are five objects in the array of 开发者_如何学Pythonpeople, then the final NSArray would just show the ages:

{ 12, 45, 23, 43, 32 }

Order is not important.


EDIT I have added a blocks based implementation too alongwith the selector based implementation.

What you are looking for is something equivalent to the "map" function from the functional world (something which, unfortunately, is not supported by Cocoa out of the box):

@interface NSArray (FunctionalUtils)
- (NSArray *)mapWithSelector:(SEL)selector;
- (NSArray *)mapWithBlock:(id (^)(id obj))block;
@end

And the implementation:

@implementation NSArray (FunctionalUtils)

- (NSArray *)mapWithSelector:(SEL)selector {
  NSMutableArray *result = [[NSMutableArray alloc] initWithCapacity:[self count]];
  for (id object in self) {
    [result addObject:[object performSelector:selector]];
  }
  return [result autorelease];
}

- (NSArray *)mapWithBlock:(id (^)(id obj))block {
  NSMutableArray *result = [[NSMutableArray alloc] initWithCapacity:[self count]];
  for (id object in self) {
    [result addObject:block(object)];
  }
  return [result autorelease];
}

@end

Now, when you need to "map" from people to their ages, you can just do this:

ages = [people mapWithSelector:@selector(age)];

OR

ages = [people mapWithBlock:^(Person *p) { return [p age]; }];

The result, ages, will be a new NSArray containing just the ages of the people. In general, this will work for any sort of simple mapping operations that you might need.

One caveat: Since it returns an NSArray, the elements inside ages should be NSNumber, not a plain old integer. So for this to work, your -age selector should return an NSNumber, not an int or NSInteger.


Assuming that each object has a method called "age" that returns an NSNumber *, you should be able to do something like the following:

-(NSArray *)createAgeArray:(NSArray *)peopleArray {
    NSMutableArray *result = [[NSMutableArray alloc] initWithCapacity:[peopleArray count]];
    [peopleArray enumerateObjectsUsingBlock:^(id person, NSUInteger i, BOOL *stop) {
        [result addObject:[person age]];
    }];
    return [result autorelease];
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜