chongzixin
chongzixin

Reputation: 1981

Objective C custom compare: with priority

I have a NSArray of countries that I obtained using [NSLocale ISOCountryCodes]. How do I sort this NSArray such that I can put certain commonly used countries at the top of the list, while keeping the rest in its alphabetical order?

United States of America
United Kingdom
Singapore
Korea
Japan
Hong Kong
Afghanistan
Albania
Algeria
etc etc..

I am using caseInsensitiveCompare: currently to get the alphabetical order, but how can I change it such that I can specify a list to put at the top, while the rest to be kept alphabetical below.

Upvotes: 1

Views: 237

Answers (3)

Natasha
Natasha

Reputation: 6893

I would do it using Sort Descriptor. I don't like manipulating array again and again. So, I find sort descriptors best in this kind of scenario. (Just personal preference)

Step 1: Create a model class with priority as a key. My model class-

#import <Foundation/Foundation.h>

@interface ISOCountry : NSObject

@property(nonatomic, strong) NSString *countryCode;
@property(nonatomic, retain) NSString *priority;

@end

Step 2: The just do this-

NSArray *ISOCountryCodes = [[NSArray alloc]initWithArray:[NSLocale ISOCountryCodes]];
NSArray *commonUsedCountries= [[NSArray alloc]initWithObjects:@"NR", @"NG", @"KW", @"ES", nil];
NSMutableArray *arrayToBeSorted = [[NSMutableArray alloc]init];

for(NSString *countryCode in ISOCountryCodes){

    ISOCountry *isoCountry = [[ISOCountry alloc] init];
    [isoCountry setValue:countryCode forKey:@"countryCode"];

    if(![commonUsedCountries containsObject:countryCode]){
        [isoCountry setValue:[NSString stringWithFormat:@"%d", 2] forKey:@"priority"];
       }
    else{
        [isoCountry setValue:[NSString stringWithFormat:@"%d", 1] forKey:@"priority"];
       }
   [arrayToBeSorted addObject:isoCountry];
}

NSSortDescriptor *prioritySort =    [[NSSortDescriptor alloc] initWithKey:@"priority" ascending:YES];
NSSortDescriptor *countryCodeSort = [[NSSortDescriptor alloc] initWithKey:@"countryCode"  ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObjects:prioritySort, countryCodeSort, nil];
NSArray *sortedArray = [arrayToBeSorted sortedArrayUsingDescriptors:sortDescriptors];

Upvotes: 1

Ievgen Leichenko
Ievgen Leichenko

Reputation: 1317

As opposed to WenchenHuang's answer (which is valid), I think you could do it with the help of sortedArrayUsingComparator. Inside the block just compare the strings as usually, but if the string equals to one of the codes that you want to show higher, return YES.

someArray = [someArray sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
    if ([(NSString*)obj1 isEqualToString:@"USA"]) {
        return YES;
    } else if ([(NSString*)obj1 isEqualToString:@"SOME_OTHER_COUNTRY"]) {
        return YES;
    }

    return [(NSString*)obj1 compare:(NSString*)obj2];
}];

Upvotes: 1

Leo
Leo

Reputation: 24714

You can delete the objects you do not want to sort,then sort the rest,then add them together. Example Code:

NSMutableArray * allData = [[NSMutableArray alloc] initWithArray:[[NSLocale ISOCountryCodes]]];
NSArray * yourexceptArray;
[allData removeObjectsInArray:yourexceptArray];
NSMutableArray * result = [[NSMutableArray alloc] initWithArray:yourexcepArray];
sortedArray = //Sort the allData as you like,then add it to result
[result addObjectsFromArray:sortedArray]

Upvotes: 1

Related Questions