简体   繁体   中英

Sorting an NSArray of Objects WRT the objects contained in NSSet in those objects

So here is the hierarchy:

NSArray A contains 3 objects. Each of those custom objects contains an NSSet of another custom objects. Each of those "another custom object"s contains a number.

I want to sort NSArray A by that number. I would not care of what object in the set was picked up. Any object from that set would be fine.

Any clues on how to do it with NSSortDescriptor ?

Key-Value coding works also with properties (or even instance variables) of custom objects, as shown in the following example. But you have to specify a collection operator that is applied to the set to choose an object for sorting, eg @max , @min or @avg .

// The "inner object", containing a number:
@interface Custom1 : NSObject
@property (nonatomic, strong) NSNumber *number;
@end

@implementation  Custom1
@end

// The "outer object", containing a set of "inner" objects:
@interface Custom2 : NSObject
@property (nonatomic, strong) NSSet *others; // set of "Custom1 objects.
@end

@implementation  Custom2
@end

Now you can do the following:

Custom1 *o1 = [[Custom1 alloc] init];
o1.number = @1;
Custom1 *o2 = [[Custom1 alloc] init];
o2.number = @2;
Custom2 *p1 = [[Custom2 alloc] init];
p1.others = [NSSet setWithObjects:o1, o2, nil];

Custom1 *o3 = [[Custom1 alloc] init];
o3.number = @3;
Custom1 *o4 = [[Custom1 alloc] init];
o4.number = @4;
Custom2 *p2 = [[Custom2 alloc] init];
p2.others = [NSSet setWithObjects:o3, o4, nil];

NSArray *array = @[p1, p2];

// Sort according to maximum number in the inner object set:
NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"others.@max.number" ascending:YES];
NSArray *sortedArray = [array sortedArrayUsingDescriptors:@[sort]];

Since the data are stored in an NSArray the sort can be done using blocks, known to a sort descriptor as a comparator. Note that this approach does not work with SQLite-backed Core Data fetches, which sort directly on the property value stored in the underlying data base.

There are several ways to go about it, this one is straight forward, bordering on the pedestrian (and I hope I got the data structure right):

NSArray *data = @[
    @{@"otherobjects":[NSSet setWithObjects: @{@"num":@2}, @{@"num":@1}, @{@"num":@4}, nil]},
    @{@"otherobjects":[NSSet setWithObjects:@{@"num":@7}, @{@"num":@9}, @{@"num":@8}, nil]}
];

NSSortDescriptor *sd = [NSSortDescriptor sortDescriptorWithKey:@"otherobjects" ascending:NO comparator:^NSComparisonResult(id obj1, id obj2) {

    NSNumber *n1 = [[obj1 anyObject] valueForKey:@"num"];
    NSNumber *n2 = [[obj2 anyObject] valueForKey:@"num"];
    return [n1 compare: n2];
}];

NSArray *sorted = [data sortedArrayUsingDescriptors:@[sd]];

If you want to get fancy, you can implement a method on your custom object which compares two objects, and then create a sort descriptor using that method, or you could declare a read-only property returning for instance the max or min value of the NSSet , and then simply use a normal sort descriptor on that property.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM