Sorting Keys of NSDictionary on the basis of its Elements’ Data.

How to sort dictionary keys using data of its items as criteria?

Tutorial of Sorting of a Dictionary - iOS Development Tips

NSDictionary is a data structure that contains unsorted items unlike an array which is an ordered collection. A dictionary is an indexed data structure which helps us identify its the items it contains, as long as we know the index key. In Objective C, the elements contained in NSDictionary can belong to any class. They could be instances of a custom class containing data populated in its properties or they could simply be the instances of NSArray containing a collection of data.

Sometimes we come across situations where we wish to store data in a dictionary data structure but occasionally we are also required to sort the dictionary on the basis of some data contained in its elements. This can be done by sorting out the keys on the basis of our data requirement. Once we have the keys sorted out we can present each element of the dictionary that corresponds to each of the keys, which are already sorted now.

Let us take following two use-cases which could require the sorting of a dictionary.

Situation 1 :

A trainer conducting a training program on iPhone Development Basics would like to access the professional details filled out by the workshop participants. He can do this on the basis of the participant id, which serves as key. A dictionary structure can suffice the requirement of keeping and accessing the data of each participant. However, in order to select the participants for an Advanced iOS Development Workshop, the trainer would like to sort the participants on the basis of their total score obtained in the various tests and quizzes.

Situation 2:

A Game development manager would like to access game development data (game features, special characters, effects used, development time, bugs fixed after shipping, sales etc.) pertaining to the games developed in the past. He can do this on the basis of a game name, which serves as key. But from time to time, he would also like to sort the games on the basis of their overall sales performance in the market. This could help him identify certain elements which he would like to incorporate in the design phase of the next game so that the new game performs better.

Both the above situations would involve keeping data in a dictionary and also the occasional sorting on the basis of the data contained in its elements.

So how is it done?

NSDictionary Class contains the following method which can help us sort the keys of a dictionary.

– (NSArray *)keysSortedByValueUsingComparator:(NSComparator)cmptr

In the above method cmptr is a comparator block and the method returns an array of keys of the dictionary on which the method is invoked. The sorting logic is written in comparator block and we can easily build our sorting criteria in the block. Let’s take an example for which you can download the XCode project zip here.

Example:

Let us take the example of a dictionary which contains information about different countries, for instance, their population in millions, national income in USD, and the language spoken. The data for each country viz. USA, Brazil, India, China, Russia, Italy, Great Britain & Saudi Arabia is contained in our dictionary with the country names as its keys.

Following method help us create the dictionary.

Method: createDictionary

//================================================================================
// Initialize instance countriesInfo
//================================================================================
-(void) createDictionary{

 //Dictionary with name of the countries as keys. The dictionary contains information as an array of Population
 //(in millions) as integer, National Income in alphanumeric as string and Language as string.
 countriesInfo = [NSDictionary dictionaryWithObjectsAndKeys:
 [NSArray arrayWithObjects:[NSNumber numberWithInt:316], @"USD 50000", @"English", nil], @"USA",
 [NSArray arrayWithObjects:[NSNumber numberWithInt:194], @"USD 12000", @"Portugese", nil], @"Brazil",
 [NSArray arrayWithObjects:[NSNumber numberWithInt:1210], @"USD 1592", @"Hindi", nil], @"India",
 [NSArray arrayWithObjects:[NSNumber numberWithInt:1353], @"USD 6075", @"Chinese", nil], @"China",
 [NSArray arrayWithObjects:[NSNumber numberWithInt:143], @"USD 14037", @"Russian", nil], @"Russia",
 [NSArray arrayWithObjects:[NSNumber numberWithInt:59], @"USD 33115]", @"Italian", nil], @"Italy",
 [NSArray arrayWithObjects:[NSNumber numberWithInt:63], @"USD 38591", @"English", nil], @"Great Britain",
 [NSArray arrayWithObjects:[NSNumber numberWithInt:29], @"USD 25000", @"Arabic", nil], @"Saudi Arabia",
 nil];

 [countriesInfo retain];

}

In the example, we sort the keys of the dictionary for the following:

1. Population
2. Language
3. National Income

The corresponding methods used in the example above are given below:

Method: sortKeysOnTheBasisOfPopulation

//======================================================================
// Sorts Country Names on the basis of Population (integer data)
//======================================================================
-(void) sortKeysOnTheBasisOfPopulation{
 //Method of NSDictionary class which sorts the keys using the logic given by the comparator block.
 NSArray * sortArray = [countriesInfo keysSortedByValueUsingComparator: ^(id obj1, id obj2) {

//Comparing the integer values of national income:

 //First value is greather than the second.
 if ([[obj1 objectAtIndex:0] intValue] > [[obj2 objectAtIndex:0] intValue]) {
 return (NSComparisonResult)NSOrderedDescending;
 }

//First value is less than the second.
 if ([[obj1 objectAtIndex:0] intValue] < [[obj2 objectAtIndex:0] intValue]) {
 return (NSComparisonResult)NSOrderedAscending;
 }

//Both the values are same
 return (NSComparisonResult)NSOrderedSame;
 }];

//Show Result in the Output Panel: Country Name and its Population
 for (int i = 0; i < [sortArray count]; i++) {
 NSLog(@"Country Name:%@ -- Population:%d",[sortArray objectAtIndex:i],
 [[[countriesInfo valueForKey:[sortArray objectAtIndex:i]] objectAtIndex:0] intValue]);
 }

}

Method: sortKeysOnTheBasisOfLanguage

//======================================================================
// Sorts Country Names on the basis of Language (string data)
//======================================================================
-(void) sortKeysOnTheBasisOfLanguageAlphabetically{

//Method of NSDictionary class which sorts the keys using the logic given by the comparator block
 NSArray * sortArray = [countriesInfo keysSortedByValueUsingComparator: ^(id obj1, id obj2) {

//We do case insensitive comparision of two strings as we are not really concerned about
 //the "content" of the strings (please see sortKeysOnTheBasisOfNationalIncome method where
 //we would like to do the comparision with numeric search as an extra option)
 NSComparisonResult result = [[obj1 objectAtIndex:2] caseInsensitiveCompare:[obj2 objectAtIndex:2]];
 return result;
 }];

//Show Result in the Output Panel: Country Name and its Language Name
 for (int i = 0; i < [sortArray count]; i++) {
 NSLog(@"Country Name:%@ -- Language:%@",[sortArray objectAtIndex:i],
 [[countriesInfo valueForKey:[sortArray objectAtIndex:i]] objectAtIndex:2]);
 }

}

Method: sortKeysOnTheBasisOfNationalIncome

//================================================================================
// Sorts Country Names on the basis of National Income (alphanumeric data)
//================================================================================
-(void) sortKeysOnTheBasisOfNationlIncome{

//Method of NSDictionary class which sorts the keys using the logic given by the comparator block
 NSArray * sortArray = [countriesInfo keysSortedByValueUsingComparator: ^(id obj1, id obj2) {

 //We do comparison with numeric search as an option because all the strings have USD <space> in the beginning
 //and the rest of the information is numeric. This option will help us sort the keys as if they are
 //integers despite being strings.
 NSComparisonResult result = [[obj1 objectAtIndex:1] compare:[obj2 objectAtIndex:1] options:NSNumericSearch];
 return result;
 }];

//Show Result in the Output Panel: Country Name and its National Income
 for (int i = 0; i < [sortArray count]; i++) {
 NSLog(@"Country Name:%@ -- National Income:%@",[sortArray objectAtIndex:i],
 [[countriesInfo valueForKey:[sortArray objectAtIndex:i]] objectAtIndex:1]);
 }

}

Important Note:

An important point to be noted is that we have used NSString’s  – (NSComparisonResult) compare:(NSString *)aString options:(NSStringCompareOptions)mask method with NSNumericSearch as the mask. In sorting the names of the countries on the basis of National Income we have to take cognizance of the fact that though national incomes are strings but the content in them is alpha-numeric. This helps us get accurate results from the sorting. For sorting the names of the countries on the basis of Language, we can simply use (NSComparisonResult)caseInsensitiveCompare:(NSString *)aString.

If you would like to view the output of the code in XCode, you can download the XCode project here.

— §§§ —

 

iOS trainings courses workshops in swift programming in India at Delhi NCR Noida Gurgaon | Indian iOS Games and apps developers | ios application development in swift objective C India | iOS apps and games development courses & trainings in Delhi NCR Noida Gurgaon India | iPhone & iPad games for eLearning | iPhone app and game development courses workshops in swift | games and apps developer & producer india | iOS games and applications development Delhi NCR Noida Gurgaon India | Apple development training courses Delhi NCR Gurgaon Noida | iPhone development trainings & classes in swift & objective C | iOS app development trainings in Noida Gurgaon Delhi NCR | iPhone & iPad Application development in India | iOS trainings for corporates & companies india | iPhone iPad games & apps development in Delhi NCR Noida Gurgaon | iPhone iPad based game development in Gurgaon Noida Delhi NCR India | mobile apps development india | Xcode iOS trainings and courses in swift for corporates & companies