How to sort NSMutableArray using sortedArrayUsingDescriptors?

I have a question about sorting NSMutableArray. I can use sortedArrayUsingDescriptors: method to sort an array with objects.

For example I have an NSMutableArray of places where I have an attribute frequency (int value) and I want to sort descending on frequency but I don’t know how to use it correctly.

  • Sort NSDictionary in ascending order
  • Sort NSArray of NSDictionary objects in Swift
  • NSSortDescriptor: Custom comparison on multiple keys simultaneously
  • How to sort Core Data fetched properties
  • How to sort an Array of Tuples?
  • Swift how to sort array of custom objects by property value
  • What do I put as a key in initWithKey?

    My object place contains:

    NSString * name;
    NSString * address;
    NSString * frequency;
    NSString * type;
    

    NSMutableArray * places;
    
    ... populate array with objects ...
    
    NSSortDescriptor * sortByFrequency =
       [[[NSSortDescriptor alloc] initWithKey:@"????????" ascending:NO] autorelease];
    
    NSArray * descriptors = [NSArray arrayWithObject:sortByFrequency];
    NSArray * sorted = [x sortedArrayUsingDescriptors:descriptors];
    

    3 Solutions Collect From Internet About “How to sort NSMutableArray using sortedArrayUsingDescriptors?”

    To sort your array of objects you:

    1. setup NSSortDescriptor – use names of your variables as keys to setup descriptor for sorting plus the selector to be executed on those keys
    2. get the array of descriptors using NSSortDescriptor that you’ve setup
    3. sort your array based on those descriptors

    Here are two examples, one using NSDictionary and NSString/NSNumber values sorting on NSNumber, the other one using custom class with sorting on two NSString fields.

    Follow Sorting and Filtering NSArray Objects in Cocoa programming topics to see more examples and explanation.

    Example:

    This was done on GNUStep it should work the same on Cocoa – the code is exactly the same – I’ll try when I sit in front of my Mac:

    First example using NSString and NSNumber values with sorting on NSNumber value:

    NSString * NAME      = @"name";
    NSString * ADDRESS   = @"address";
    NSString * FREQUENCY = @"frequency";
    NSString * TYPE      = @"type";
    
    NSMutableArray * array = [NSMutableArray array];
    
    NSDictionary * dict;
    
    dict = [NSDictionary dictionaryWithObjectsAndKeys:
                @"Alehandro", NAME, @"Sydney", ADDRESS,
                [NSNumber numberWithInt:100], FREQUENCY,
                @"T", TYPE, nil];
    [array addObject:dict];
    
    dict = [NSDictionary dictionaryWithObjectsAndKeys:
                @"Xentro", NAME, @"Melbourne", ADDRESS,
                [NSNumber numberWithInt:50], FREQUENCY,
                @"X", TYPE, nil];
    [array addObject:dict];
    
    dict = [NSDictionary dictionaryWithObjectsAndKeys:
                @"John", NAME, @"Perth", ADDRESS,
                [NSNumber numberWithInt:75],
                FREQUENCY, @"A", TYPE, nil];
    [array addObject:dict];
    
    dict = [NSDictionary dictionaryWithObjectsAndKeys:
                @"Fjord", NAME, @"Brisbane", ADDRESS,
                [NSNumber numberWithInt:20], FREQUENCY,
                @"B", TYPE, nil];
    [array addObject:dict];
    

    Sorting part using descriptors with the Frequency field which is NSNumber:

    NSSortDescriptor * frequencyDescriptor =
        [[[NSSortDescriptor alloc] initWithKey:FREQUENCY
                                     ascending:YES] autorelease];
    
    id obj;
    NSEnumerator * enumerator = [array objectEnumerator];
    while ((obj = [enumerator nextObject])) NSLog(@"%@", obj);
    
    NSArray * descriptors =
        [NSArray arrayWithObjects:frequencyDescriptor, nil];
    NSArray * sortedArray =
        [array sortedArrayUsingDescriptors:descriptors];
    
    NSLog(@"\nSorted ...");
    
    enumerator = [sortedArray objectEnumerator];
    while ((obj = [enumerator nextObject])) NSLog(@"%@", obj);
    

    OUTPUT – sorted by Frequency field:

    2009-12-04 x[1] {address = Sydney; frequency = 100; name = Alehandro; type = T; }
    2009-12-04 x[1] {address = Melbourne; frequency = 50; name = Xentro; type = X; }
    2009-12-04 x[1] {address = Perth; frequency = 75; name = John; type = A; }
    2009-12-04 x[1] {address = Brisbane; frequency = 20; name = Fjord; type = B; }
    2009-12-04 x[1]
    Sorted ...
    2009-12-04 x[1] {address = Brisbane; frequency = 20; name = Fjord; type = B; }
    2009-12-04 x[1] {address = Melbourne; frequency = 50; name = Xentro; type = X; }
    2009-12-04 x[1] {address = Perth; frequency = 75; name = John; type = A; }
    2009-12-04 x[1] {address = Sydney; frequency = 100; name = Alehandro; type = T; }
    


    Second example with custom class and sorting on two NSString variables.

    Array to sort (see class A at the bottom):

    NSMutableArray * array = [NSMutableArray array];
    [array addObject:[[A alloc] initWithFirstName:@"Alehandro"
                                         lastName:@"Xentro"
                                              age:[NSNumber numberWithInt:40]]];
    [array addObject:[[A alloc] initWithFirstName:@"John"
                                         lastName:@"Smith"
                                              age:[NSNumber numberWithInt:30]]];
    [array addObject:[[A alloc] initWithFirstName:@"John"
                                         lastName:@"Smyth"
                                              age:[NSNumber numberWithInt:25]]];
    [array addObject:[[A alloc] initWithFirstName:@"Torro"
                                         lastName:@"Ola"
                                              age:[NSNumber numberWithInt:45]]];
    [array addObject:[[A alloc] initWithFirstName:@"Alehandro"
                                         lastName:@"Bento"
                                              age:[NSNumber numberWithInt:41]]];
    [array addObject:[[A alloc] initWithFirstName:@"Alehandro"
                                         lastName:@"Axel"
                                              age:[NSNumber numberWithInt:41]]];
    

    The sorting part, sort on lastName then firstName:

    NSString * LASTNAME = @"lastName";
    NSString * FIRSTNAME = @"firstName";
    
    NSSortDescriptor *lastDescriptor =
        [[[NSSortDescriptor alloc]
            initWithKey:LASTNAME
              ascending:YES
               selector:@selector(localizedCaseInsensitiveCompare:)] autorelease];
    
    NSSortDescriptor *firstDescriptor =
        [[[NSSortDescriptor alloc]
            initWithKey:FIRSTNAME
              ascending:YES
               selector:@selector(localizedCaseInsensitiveCompare:)] autorelease];
    
    NSArray * descriptors =
       [NSArray arrayWithObjects:lastDescriptor, firstDescriptor, nil];
    NSArray * sortedArray =
       [array sortedArrayUsingDescriptors:descriptors];
    

    Print the result:

    NSLog(@"\nSorted ...");
    
    enumerator = [sortedArray objectEnumerator];
    while ((obj = [enumerator nextObject])) NSLog(@"%@", obj);
    

    Result (before and after sorting):

    2009-12-04 00:52:16.637 x[11375] Alehandro, Xentro, age:40
    2009-12-04 00:52:16.644 x[11375] John, Smith, age:30
    2009-12-04 00:52:16.644 x[11375] John, Smyth, age:25
    2009-12-04 00:52:16.644 x[11375] Torro, Ola, age:45
    2009-12-04 00:52:16.645 x[11375] Alehandro, Bento, age:41
    2009-12-04 00:52:16.645 x[11375] Alehandro, Axel, age:41
    2009-12-04 00:52:16.645 x[11375]
    Sorted ...
    2009-12-04 00:52:16.645 x[11375] Alehandro, Axel, age:41
    2009-12-04 00:52:16.645 x[11375] Alehandro, Bento, age:41
    2009-12-04 00:52:16.645 x[11375] Torro, Ola, age:45
    2009-12-04 00:52:16.645 x[11375] John, Smith, age:30
    2009-12-04 00:52:16.645 x[11375] John, Smyth, age:25
    2009-12-04 00:52:16.645 x[11375] Alehandro, Xentro, age:40
    

    Class A extends NSObject – nothing special here:

    #import <Foundation/Foundation.h>
    
    @interface A : NSObject
    {
        NSString * firstName;
        NSString * lastName;
        NSNumber * age;
    }
    
    - (id)initWithFirstName:(NSString*)aFirstName
                   lastName:(NSString*)aLastName
                        age:(NSNumber*)anAge;
    
    -(NSString* )description;
    +(NSString*)action;
    
    @end
    

    Implementation:

    #import <Foundation/Foundation.h>
    #import "A.h"
    
    @implementation A
    
    - (id)init
    {
        return [self initWithFirstName:@"N/A"
                              lastName:@"N/A"
                                   age:0];
    }
    
    - (id)initWithFirstName:(NSString*)aFirstName
                   lastName:(NSString*)aLastName
                        age:(NSNumber*)anAge
    {
        self = [super init];
        if (!self) return nil;
    
        firstName = [aFirstName copy];
        lastName = [aLastName copy];
        age = [anAge copy];
    
        return self;
    }
    
    - (void)dealloc
    {
        [firstName release];
        [lastName release];
        [age release];
        [super release];
    }
    

    - (NSString *) description
    {
        return [NSString stringWithFormat: @"%@, %@, age:%@",
                                           firstName, lastName, age];
    }
    @end
    

    The “key” is a method of your objects (the elements of your array “x”) that returns the thing you want to sort by. So in this case, you said that you want to sort by the “frequency”. Then all you have to do is use the name of the method that returns the frequency, as the key.

    Here’s how a would sort an NSMutableArray:

    NSMutableArray *numberSort =[[NSMutableArray alloc] init];
    
        while ((key = [enumerator nextObject])) {
            //(NSNumber *)integer = [key integerValue];
            [numberSort  addObject:[NSNumber numberWithInt:[key intValue]]];
            // code that uses the returned key 
        }
    
    
        NSArray *stringSort = [numberSort sortedArrayUsingSelector:@selector(compare:)];
        enumerator = [stringSort objectEnumerator];
        NSNumber  *intKey;
    
        NSMutableArray *backToString =[[NSMutableArray alloc] init];
    
        while ((intKey = [enumerator nextObject])) {
            //(NSNumber *)integer = [key integerValue];
            [backToString  addObject:[intKey stringValue]];
            // code that uses the returned key