Sort Array Of Dictionaries With NSSortDescriptor

In an earlier post I wrote about the basics of working with dictionaries (NSDictionary objects). This is a follow on post to show one way to sort the array of dictionary objects:

Let’s begin with this array of dictionaries:

// Define keys for dictionary values
NSString *style = @"Style";
NSString *appearance = @"Appearance";
NSString *hopProfile = @"Bitterness";
 
// A dictionary object
NSDictionary *dict;
 
// Create array to hold dictionaries 
NSMutableArray *arrayOfDictionaries = [NSMutableArray array];
 
// Create three dictionaries
dict = [NSDictionary dictionaryWithObjectsAndKeys:
                    // Key value pairs  
                     @"India Pale Ale (IPA)", style, 
                     @"Copper", appearance, 
                     [NSNumber numberWithInt:50], hopProfile, 
                     nil];
[arrayOfDictionaries addObject:dict];
 
dict = [NSDictionary dictionaryWithObjectsAndKeys:
                    // Key value pairs
                     @"Bock", style,    
                     @"Deep Gold", appearance, 
                     [NSNumber numberWithInt:25], hopProfile, 
                     nil];
[arrayOfDictionaries addObject:dict];
 
dict = [NSDictionary dictionaryWithObjectsAndKeys:
                   @"Stout", style, 
                   @"Jet Black", appearance, 
                   [NSNumber numberWithInt:35], hopProfile, 
                   nil];
[arrayOfDictionaries addObject:dict];
 
dict = [NSDictionary dictionaryWithObjectsAndKeys:
                   @"English Brown Ale", style, 
                   @"Copper", appearance, 
                   [NSNumber numberWithInt:25], hopProfile, 
                   nil];
[arrayOfDictionaries addObject:dict];
 
NSLog(@"array of dictionaries: %@", arrayOfDictionaries);

The output (before sorting):

 array of dictionaries: (
        {
        Appearance = Copper;
        Bitterness = 50;
        Style = "India Pale Ale (IPA)";
    },
        {
        Appearance = "Jet Black";
        Bitterness = 35;
        Style = Stout;
    },
        {
        Appearance = Copper;
        Bitterness = 25;
        Style = "English Brown Ale";
    },
        {
        Appearance = "Deep Gold";
        Bitterness = 25;
        Style = Bock;
    }
)
NSSortDescriptor

Sort descriptors (NSSortDescriptor) are used to describe a sorting order. For example, the descriptor below shows how to sort an array based on the hopProfile value:

NSSortDescriptor *hopProfileDescriptor =
  [[NSSortDescriptor alloc] initWithKey:hopProfile
                               ascending:YES];
 
NSArray *descriptors = [NSArray arrayWithObjects:hopProfileDescriptor, nil];
NSArray *sortedArrayOfDictionaries = [arrayOfDictionaries sortedArrayUsingDescriptors:descriptors];
 
NSLog(@"sorted array of dictionaries: %@", sortedArrayOfDictionaries);

The array of dictionaries is now sorted by ‘Bitterness’:

sorted array of dictionaries: (
        {
        Appearance = Copper;
        Bitterness = 25;
        Style = "English Brown Ale";
    },
        {
        Appearance = "Deep Gold";
        Bitterness = 25;
        Style = Bock;
    },
        {
        Appearance = "Jet Black";
        Bitterness = 35;
        Style = Stout;
    },
        {
        Appearance = Copper;
        Bitterness = 50;
        Style = "India Pale Ale (IPA)";
    }
)
Multiple NSSortDescriptors

Multiple sort descriptors provide another level of detail for arranging data, the code below adds another sort descriptor to sort based on the style key:

NSSortDescriptor *hopProfileDescriptor =
  [[NSSortDescriptor alloc] initWithKey:hopProfile
                             ascending:YES];
 
NSSortDescriptor *appearanceDescriptor =
  [[NSSortDescriptor alloc] initWithKey:style
                             ascending:YES
                             selector:@selector(localizedCaseInsensitiveCompare:)];
 
NSArray *descriptors = [NSArray arrayWithObjects:hopProfileDescriptor, appearanceDescriptor, nil];
NSArray *sortedArrayOfDictionaries = [arrayOfDictionaries sortedArrayUsingDescriptors:descriptors];
 
NSLog(@"sorted array of dictionaries: %@", sortedArrayOfDictionaries);

Now, the output is sorted first by hopProfile, followed by style:

sorted array of dictionaries: (
        {
        Appearance = "Deep Gold";
        Bitterness = 25;
        Style = Bock;
    },
        {
        Appearance = Copper;
        Bitterness = 25;
        Style = "English Brown Ale";
    },
        {
        Appearance = "Jet Black";
        Bitterness = 35;
        Style = Stout;
    },
        {
        Appearance = Copper;
        Bitterness = 50;
        Style = "India Pale Ale (IPA)";
    }
)
  1. I realize you assigned bitterness to a string, but can you sort data as a subset, or do you need to create a NEW array that is only a subset of the entire dictionary? E.G. Create a subset/sort of the data if Bitterness is > 30 (assuming bitterness is now a int/float/etc)?

Comments are closed.