How to sort numbers in NSArray?
Asked Answered
G

5

10

I can't piece together how to do this.

I fetch my array from a plist, this array is full of numbers (as set in the plist). Now al I need to do is sort them so they are descending, but I can't work it out.

Gronseth answered 24/6, 2012 at 16:48 Comment(0)
B
43

Try this code?

 NSArray *array = /* loaded from file */;
 array = [array sortedArrayUsingSelector: @selector(compare:)];
Blum answered 24/6, 2012 at 16:53 Comment(10)
But what would the contents of the selector method be? This is what gets me.Gronseth
The -compare: method is defined for NSNumber instances: developer.apple.com/library/mac/documentation/Cocoa/Reference/…:Blum
Thats the one I meant. Perhaps I misunderstanding the docs, but I have tried with and without the compare method and it always crashing the app saying unrecognised selector.Gronseth
That's weird. Something must be up with your array then.Blum
Hmm, its literally an arrays which looks like this: 1, 54, 23, 11, 8, 67. I'll look further into it.Gronseth
It seems that (from your comment on the other answer) that you've populated your .plist with numbers as strings and not as numbers.Blum
Am I the only one who finds this stupidly complicated? There's seriously no method for NSArray called sortedArray which calls exactly this? I love extensions and all, but why do I (and everyone else) have to write such basic stuff that Apple should have had in the standard libraries all along? Although Obj-C is a flawed language and Swift can't come quickly enough, it seems to me a bigger problem is the lousy libraries. I hope Swift's libraries don't leave me having to write out this basic stuff myself.Anaerobic
@ArtOfWarfare: Since Arrays can hold any type of object, including entire subarrays and dictionaries, it's impossible to have a generic sorting routine that automatically knows how to sort your objects. Let's say you have an array of UIViewControllers. How should they be sorted?Santee
@OwenHartnett - It should always use compare:. If the class you've inserted into your NSArray doesn't implement that method, then you shouldn't be using the sortedArray method. You'll have to fall back to the more flexible sortedArrayUsingSelector: method.Anaerobic
You can't always use compare: . In objective C, arrays can hold mixed types: You might have a string, and NSNumber, a UIViewController and a NSDate all in the same array, yet there may be logical reason where a sort is appropriate. Having a generic compare: as a default method could generate unattainable expectations and be very difficult to debug without checking the types of the array items.Santee
S
16

The following will sort the numbers in ascending order and then reverse the result to give the numbers in descending order:

NSArray *sorted = [[[array sortedArrayUsingSelector:@selector(compare:)] reverseObjectEnumerator] allObjects];

This previous question has some other alternatives: Sort an NSArray in Descending Order

Sachasachem answered 24/6, 2012 at 17:7 Comment(4)
Im getting a crash with -[__NSCFString sortedArrayUsingSelector:]: unrecognized selector sent to instance.Gronseth
Are you sure you calling sortedArrayUsingSelector: on an NSArray? You appear to be calling sortedArrayUsingSelector: on an NSString. You should probably check the data structure that is being loaded from the Plist.Sachasachem
@Josh Kahane, if so, you are most likely having issues with memory management, because your array pointer points to NSString object. Forgot to retain / too much [auto]releases?Occasional
This answer fully answer's the question, as it sorts the array descending.Decanter
O
13

Here is one of many methods using comparison block. This code snippet is handy for any array with numbers that you want to sort. For Ascending order:

AscendingArray = [UnsortArray sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
    if ([obj1 integerValue] > [obj2 integerValue]) {
      return (NSComparisonResult)NSOrderedDescending;
    }

    if ([obj1 integerValue] < [obj2 integerValue]) {
      return (NSComparisonResult)NSOrderedAscending;
    }
    return (NSComparisonResult)NSOrderedSame;
  }];

For Descending order:

DescendingArray = [UnsortArray sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
    if ([obj1 integerValue] > [obj2 integerValue]) {
      return (NSComparisonResult)NSOrderedAscending;
    }

    if ([obj1 integerValue] < [obj2 integerValue]) {
      return (NSComparisonResult)NSOrderedDescending;
    }
    return (NSComparisonResult)NSOrderedSame;
  }];
Octagonal answered 4/3, 2015 at 17:19 Comment(2)
why not just use NSNumber compare:?Hygrometry
I've used this method because even if some of my data are numbers, I've stored everything as string. This method can compare numbers that are stored as strings, contrary to compare: methodCatsup
E
5

It work for me:

NSSortDescriptor *sortIdClient = 
[NSSortDescriptor sortDescriptorWithKey:@"campaignValue"
                              ascending:NO
                             comparator: ^(id obj1, id obj2){

    return [obj1 compare:obj2 options:NSNumericSearch];

 }];

NSArray *sortDescriptors = @[sortIdClient];

NSArray *arrTemp = [self.allCampaignsList sortedArrayUsingDescriptors:sortDescriptors];
Exemplificative answered 27/11, 2014 at 3:59 Comment(0)
M
0

This Will solve the problem:

 NSArray *array = /* loaded from file */;
 array = [array sortedArrayUsingSelector: @selector(compare:)];
Mosul answered 9/8, 2016 at 12:12 Comment(1)
please remove extra indentation which makes text be shown as codeWrote

© 2022 - 2024 — McMap. All rights reserved.