Centurion
Centurion

Reputation: 14314

How to filter an array using an array?

I have three types of custom classes (see below) and three arrays componentList, componentGroupList and componentGroupItemList. Arrays are not linked, each of them contain all objects. I need to filter specific component, all its related groups and all their related items.

Now, I know how to filter componentList using @"componentId==123" and get desired component object. I can also filter its groups from componentGroupList using the same predicate, because ComponentGroup object contains the same componentId key. However, I don't know how to filter related ComponentGroupItem objects from componentGroupItemList.

Currently, I have filtered array containing ComponentGroup objects, and I would like to filter componentGroupItemList using that array. Is it possible, or do I need to extract all "groupId" values from filteredComponentGroupList into a string and then make some predicate?

The classes:

@interface Component : NSObject

  @property (nonatomic, strong) NSNumber *componentId;
  @property (nonatomic, strong) NSString *title;

@end

@interface ComponentGroup : NSObject

  @property (nonatomic, strong) NSNumber *groupId;
  @property (nonatomic, strong) NSNumber *componentId;
  @property (nonatomic, strong) NSString *title;

@end

@interface ComponentGroupItem : NSObject

  @property (nonatomic, strong) NSNumber *itemId;
  @property (nonatomic, strong) NSNumber *groupId;
  @property (nonatomic, strong) NSString *title;

@end

Upvotes: 0

Views: 102

Answers (2)

Monolo
Monolo

Reputation: 18253

At a first glance your data structure seems a bit redundant, but I guess you have thought it through.

If I understand your requirements correctly, you have an array of component groups already filtered (let's call it filteredComponentGroups) and you wish to filter another array (componentGroupItemList) using filteredComponentGroups.

In that case you can use the IN operator of NSPredicate and construct the array of IDs with valueForKey: on the array. valueForKey: on an array constructs a new array with only the values of that key of each object in the original collection. Very powerful for situations like this one.

 NSArray *filteredComponentGroups = // ... your filtered components

 NSArray *componentIdsFromFilteredComponentGroups = [filteredComponentGroups valueForKey: @"groupId"];
 NSPredicate *inFilteredComponentGroupsP = [NSPredicate predicateWithFormat: @"groupId IN %@", componentIdsFromFilteredComponentGroups];

 NSArray *filteredGroupItemList = [componentGroupItemList filteredArrayUsingPredicate: inFilteredComponentGroupsP];

Typed directly in the browser, so beware of typos.

Upvotes: 2

Martin R
Martin R

Reputation: 540075

You have to extract the group ids first

NSArray *groupIds = [filteredComponentGroupList valueForKey:@"groupId"];

and use that for a predicate

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"groupId IN %@", groupIds];
NSArray *filteredComponentGroupItemList = [componentGroupItemList filteredArrayUsingPredicate:predicate];

Upvotes: 3

Related Questions