denikov
denikov

Reputation: 869

ios sortedArrayUsingComparator but keeping some values always in the beginning

I'm sorting an array like this:

NSArray *temp = [array sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
    int first = [[a valueForKey:@"id"] intValue];
    int second = [[b valueForKey:@"id"]intValue];
    if (first > second) return NSOrderedAscending;
    if (first < second) return NSOrderedDescending;
    return NSOrderedSame;
}];
return [temp mutableCopy];

Works perfectly but now I want to add a check to see if, for example, a's value for key is equal to a certain value, always keep it at the top of the array, no matter what the "id" value is. Is it possible to do this using the comparator?

Upvotes: 1

Views: 890

Answers (3)

Zee
Zee

Reputation: 1905

Lets assume your certain value is 5, then change code as

NSArray *temp = [array sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
    int first = [[a valueForKey:@"id"] intValue];
    int second = [[b valueForKey:@"id"] intValue];
    int foo = [[a valueForKey:@"foo"] intValue]; // get foo

    if (foo == 5) return NSOrderedAscending;    // send foo to the top/bottom
    if (first > second) return NSOrderedAscending;
    if (first < second) return NSOrderedDescending;
    return NSOrderedSame;
}];
return [temp mutableCopy];

Upvotes: 3

Duncan C
Duncan C

Reputation: 131481

You are free to write whatever code you want in your comparator function. Zee's code should solve your problem for you.

Note that you might want to avoid using key-value coding ("valueForKey") if possible, since it's slower than other methods of fetching a value. If the objects in your array are dictionaries, use objectForKey. If the array contains custom objects with properties that you use for sorting, then just reference the property directly. In both cases you'll have to cast the object to the appropriate type, but that's trivial, e.g.:

^NSComparisonResult(NSDictionary *a, NSDictionary *b) {
    int first = [a[@"id] intValue];
    int second = [b[@"id] intValue];

    int foo = [a[@"foo"] intValue]; // get foo
    if (foo == 5) return NSOrderedAscending;    // send foo to the top/bottom
    if (first < second) return NSOrderedDescending;
    if (first > second) return NSOrderedAscending;
    return NSOrderedSame;
}
##How comparator based sorting works:##

You send an array a sortedArrayUsingComparator message, along with a comparator block that knows how to compare 2 items in the array.

The sort method then runs through all the objects in your array, invoking your code to compare pairs of objets and decide what order they belong in. The sort method is free to use whatever sort algorithm is best for the current situation (number of items, type of private concrete array subclass that is being used, etc.) If the sort method decides to use quick sort, or heap sort, or even a bubble sort, you don't need to care. Since your comparator tells it how to compare a pair of objects, it can create a sorted array for you.

Upvotes: 1

Fernando Mazzon
Fernando Mazzon

Reputation: 3591

NSArray *temp = [array sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
    int first = [[a valueForKey:@"id"] intValue];
    int second = [[b valueForKey:@"id"]intValue];
    if (first > second || (yourOverridingConditionGoesHere)) return NSOrderedAscending;
    if (first < second) return NSOrderedDescending;
    return NSOrderedSame;
}];
return [temp mutableCopy];

Upvotes: 1

Related Questions