Padin215
Padin215

Reputation: 7484

Sort NSArray based on derived value… with a hitch?

I want to be able to sort a NSArray of objects based on its tag value. The hitch is if the tag is 0, I want it pushed to the end of the array.

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"tag" ascending:TRUE];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];

NSArray *sortedArray = [self.array sortedArrayUsingDescriptors:sortDescriptors];

This returns with all the objects with tags in the front of the index (like it should).

I want a tag value > 0 to be at the front, and all the tag values of 0 at the end.

I though blocks would work, something similar to:

NSArray *sortedArray;
sortedArray = [drinkDetails sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
    NSDate *first = [(Person*)a birthDate];
    NSDate *second = [(Person*)b birthDate];
    return [first compare:second];
}];

that I found in another SO question, but unsure how to add the condition

if (obj.tag == 0) {
    // push to end of array
}

Any suggestions?

Upvotes: 0

Views: 125

Answers (2)

yc.lin
yc.lin

Reputation: 379

// sort the part without tag = 0
NSPredicate* p = [NSPredicate predicateWithFormat: @"tag != 0"];
NSSortDescriptor* sort = [NSSortDescriptor sortDescriptorWithKey: @"tag" ascending: YES];
NSMutableArray* result = [[[videos filteredArrayUsingPredicate: p]
                           sortedArrayUsingDescriptors: @[ sort ]] mutableCopy];

// append the part with tag = 0;
p = [NSPredicate predicateWithFormat: @"tag = 0"];
[result addObjectsFromArray: [videos filteredArrayUsingPredicate: p]];

Another approach, splice the original array to two parts, sort part without the 0s, and then append the part with 0s to the end.

Upvotes: 0

Jim Puls
Jim Puls

Reputation: 81132

You've found the idea of a comparator block; all you need to do in that block is say that an object with tag 0 sorts after anything else.

sortedArray = [self.array sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
    NSInteger first = [a tag];
    NSInteger second = [b tag];
    if (first == 0) {
        return (second == 0 ? NSOrderedSame : NSOrderedDescending);
    }
    if (second == 0) {
        return NSOrderedAscending;
    }
    if (first < second) {
        return NSOrderedAscending;
    }
    if (first > second) {
        return NSOrderedDescending;
    }
    return NSOrderedSame;
}];

Upvotes: 4

Related Questions