52

I'm trying to make a high score table, and suck at arrays in objective c (actually, in general objective c is challenging for me), so I can't figure out how to sort. I'm trying to do something like this (speudocode, I'm writing this in actionscript style because I'm more comfortable with it):

highscores.addObjecttoArray(score)
highscores.sort(ascending)

But I can't figure it out... I've seen other threads about it, but their use plist files and stuff and I don't know enough objective c to learn from them.

meman32
  • 766
  • 2
  • 6
  • 9
  • You should read up on NSPredicate and Predicate Programming topics. Understanding predicates makes a lot of things easier in Obj-c but its not something most initial training resources spend any time one. – TechZen Jul 08 '10 at 17:08
  • 1
    @TechZen, I think you mean NSSortDescriptior? – ohhorob Jul 08 '10 at 20:47
  • Ah, yes. My brain insist on transposing NSSortDescriptior and NSPredicate about half the time. Still my advice was sound if off topic. – TechZen Jul 09 '10 at 13:01

7 Answers7

142

Would you like to do that the short way?

If you have a mutable array of NSNumber instances:

NSSortDescriptor *highestToLowest = [NSSortDescriptor sortDescriptorWithKey:@"self" ascending:NO];
[mutableArrayOfNumbers sortUsingDescriptors:[NSArray arrayWithObject:highestToLowest]];

Nice and easy :)

You can also perform similar sorting with descriptors on immutable arrays, but you will end up with a copy, instead of in-place sorting.

ohhorob
  • 11,695
  • 7
  • 41
  • 50
  • Nice and Easy baby ;) – Atef Feb 14 '14 at 14:34
  • 1
    For clarification (and optimisation): `NSSortDescriptor *highestToLowest = [NSSortDescriptor sortDescriptorWithKey:@"self" ascending:NO]; NSArray * sortedArray = [mutArray sortedArrayUsingDescriptors:@[highestToLowest]];` – mylogon Nov 24 '15 at 01:53
  • A sort descriptor is typically working with instances of objects that need sorting. You specify the key to be a property of the object used for ordering. If it were instances of say "People" class, you might use a key of `"firstName"`. In this case the `NSNumber` object has no properties to be specified as the key, so a special property `"self"` is used for reference to the value of the number itself! – ohhorob Jun 01 '17 at 23:49
28

[highscores sortUsingSelector:@selector(compare:)];

Should work if they're definitely all NSNumbers.

(Adding an object is:

[highscores addObject:score];

)

If you want to sort descending (highest-first):

10.6/iOS 4:

[highscores sortUsingComparator:^(id obj1, id obj2) {
    if (obj1 > obj2)
        return NSOrderedAscending;
    else if (obj1 < obj2)
        return NSOrderedDescending;

    return NSOrderedSame;
}];

Otherwise you can define a category method, e.g.:

@interface NSNumber (CustomSorting)

- (NSComparisonResult)reverseCompare:(NSNumber *)otherNumber;

@end

@implementation NSMutableArray (CustomSorting)

- (NSComparisonResult)reverseCompare:(NSNumber *)otherNumber {
    return [otherNumber compare:self];
}

@end

And call it:

[highscores sortUsingSelector:@selector(reverseCompare:)];

Wevah
  • 28,182
  • 7
  • 83
  • 72
3

I tried the answer provided by ohhorob, but the objects were still being sorted alphabetically. Then I ran across this in another answer (https://stackoverflow.com/a/4550451/823356):

I changed my NSSortDescriptor and it now sorts numerically.

NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"score"
                                               ascending:YES
                                              comparator:^(id obj1, id obj2) {
    return [obj1 compare:obj2 options:NSNumericSearch];
}];

I just thought I'd drop this in here as it solved my 'alphabetical sorting of NSNumbers' problem

Community
  • 1
  • 1
2

For all it's worth, here is another shorthand method:

NSArray* n = @[@8, @3, @1, @12, @16, @7, @0, @5];

NSArray* asc = [n sortedArrayUsingComparator:^NSComparisonResult(NSNumber* n1, NSNumber* n2) {
            return [n1 compare:n2];
        }];
NSLog(@"Ascending: %@", asc);

NSArray* dec = [n sortedArrayUsingComparator:^NSComparisonResult(NSNumber* n1, NSNumber* n2) {
           return [n2 compare:n1];
       }];
NSLog(@"Descending: %@", dec);
Mike M
  • 4,879
  • 5
  • 38
  • 58
0

This code will sort an NSMutableArray of NSNumber in ascending order:

[tempRA sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
    return [obj1 compare:obj2];
}];

This code will sort an NSMutableArray of NSNumber in descending order:

[tempRA sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
    return [obj1 compare:obj2] * -1; // reverse the enum
}];

The code uses the fact that the NSNumber compare: method returns an NSComparisonResult that ranges from -1 to 1. Multiplying the result of the compare by -1 reverses the result and thereby reverses the sort to descending order.

0

distance is a key and it's value link (float or double)

NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"distance"
ascending:YES
comparator:^(id obj1, id obj2)
                     {
                  return [obj1 compare:obj2 options:NSNumericSearch];
                     }];
NSArray *myArray = [NSArray arrayWithArray:arraySubCat];
myArray=[myArray sortedArrayUsingDescriptors:[NSArray arrayWithObjects:sortDescriptor,nil]];
arraySubCat = [myArray copy];
Rahul Patel
  • 179
  • 1
  • 5
-1

For Descending Order:

NSArray *DescendingArray = [MinMaxArray sortedArrayUsingDescriptors:
                                @[[NSSortDescriptor sortDescriptorWithKey:@"doubleValue"
                                                                ascending:NO]]];

For ascending Order

NSArray *AscendingArray = [MinMaxArray sortedArrayUsingDescriptors:
                                @[[NSSortDescriptor sortDescriptorWithKey:@"doubleValue"
                                                                ascending:YES]]];
Ramdhas
  • 1,765
  • 1
  • 18
  • 26