How to sort a NSArray alphabetically?
Asked Answered
C

7

382

How can I sort an array filled with [UIFont familyNames] into alphabetical order?

Cadence answered 29/8, 2009 at 11:16 Comment(0)
A
735

The simplest approach is, to provide a sort selector (Apple's documentation for details)

Objective-C

sortedArray = [anArray sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];

Swift

let descriptor: NSSortDescriptor = NSSortDescriptor(key: "YourKey", ascending: true, selector: "localizedCaseInsensitiveCompare:")
let sortedResults: NSArray = temparray.sortedArrayUsingDescriptors([descriptor])

Apple provides several selectors for alphabetic sorting:

  • compare:
  • caseInsensitiveCompare:
  • localizedCompare:
  • localizedCaseInsensitiveCompare:
  • localizedStandardCompare:

Swift

var students = ["Kofi", "Abena", "Peter", "Kweku", "Akosua"]
students.sort()
print(students)
// Prints "["Abena", "Akosua", "Kofi", "Kweku", "Peter"]"

Reference

Antiproton answered 29/8, 2009 at 11:21 Comment(4)
Documentation link is outdated, code sample isn't really enough to actually sort the array. localizedCaseInsensitiveCompare: needs to be defined somehow.Paulettepauley
I updated the link. Thanks for pointing that out. localizedCaseInsensitiveCompare: is a method of NSString and should be sufficient to sort an array of strings.Antiproton
And this can be easily applied to an array containing any custom objects (not just NSString). You just have to make sure that all objects inside your array have implemented the message that the selector is specifying. Then inside this message you just call the NSString compare for the properties of your object that you want to compare.Defoliant
Such simple things must not be so complex.Piave
B
281

The other answers provided here mention using @selector(localizedCaseInsensitiveCompare:) This works great for an array of NSString, however if you want to extend this to another type of object, and sort those objects according to a 'name' property, you should do this instead:

NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES];
sortedArray=[anArray sortedArrayUsingDescriptors:@[sort]];

Your objects will be sorted according to the name property of those objects.

If you want the sorting to be case insensitive, you would need to set the descriptor like this

NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES selector:@selector(caseInsensitiveCompare:)];
Beata answered 6/11, 2012 at 0:21 Comment(4)
+1, Thank you. Funny this is the more common use case than the accepted answer.Maiden
this sorts capital letters first and then small lettersCivilize
+1, The sort descriptor along with selector is exactly what I wanted and no other answer had this. Thanks a lot manBurdett
I get an error when I try to sort an array of strings this way, because name is not a valid key. What key do I use to sort strings alphabetically with an NSSortDescriptor?Itemized
B
29

A more powerful way of sorting a list of NSString to use things like NSNumericSearch :

NSArray *sortedArrayOfString = [arrayOfString sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
            return [(NSString *)obj1 compare:(NSString *)obj2 options:NSNumericSearch];
        }];

Combined with SortDescriptor, that would give something like :

NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES comparator:^NSComparisonResult(id obj1, id obj2) {
        return [(NSString *)obj1 compare:(NSString *)obj2 options:NSNumericSearch];
    }];
NSArray *sortedArray = [anArray sortedArrayUsingDescriptors:[NSArray arrayWithObject:sort]];
Bloomery answered 15/10, 2013 at 19:19 Comment(0)
E
12

Another easy method to sort an array of strings consists by using the NSString description property this way:

NSSortDescriptor *valueDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"description" ascending:YES];
arrayOfSortedStrings = [arrayOfNotSortedStrings sortedArrayUsingDescriptors:@[valueDescriptor]];
Eulaliaeulaliah answered 21/7, 2015 at 13:40 Comment(1)
That seems a bit useless; there's no reason to sort strings this way (and there's probably a performance hit for doing so), and for other objects, its description property is rarely useful for sorting purposes.Duprey
P
10

Use below code for sorting in alphabetical order:

    NSArray *unsortedStrings = @[@"Verdana", @"MS San Serif", @"Times New Roman",@"Chalkduster",@"Impact"];

    NSArray *sortedStrings =
    [unsortedStrings sortedArrayUsingSelector:@selector(compare:)];

    NSLog(@"Unsorted Array : %@",unsortedStrings);        
    NSLog(@"Sorted Array : %@",sortedStrings);

Below is console log :

2015-04-02 16:17:50.614 ToDoList[2133:100512] Unsorted Array : (
    Verdana,
    "MS San Serif",
    "Times New Roman",
    Chalkduster,
    Impact
)

2015-04-02 16:17:50.615 ToDoList[2133:100512] Sorted Array : (
    Chalkduster,
    Impact,
    "MS San Serif",
    "Times New Roman",
    Verdana
)
Punkah answered 2/4, 2015 at 10:51 Comment(0)
K
3

This already has good answers for most purposes, but I'll add mine which is more specific.

In English, normally when we alphabetise, we ignore the word "the" at the beginning of a phrase. So "The United States" would be ordered under "U" and not "T".

This does that for you.

It would probably be best to put these in categories.

// Sort an array of NSStrings alphabetically, ignoring the word "the" at the beginning of a string.

-(NSArray*) sortArrayAlphabeticallyIgnoringThes:(NSArray*) unsortedArray {

    NSArray * sortedArray = [unsortedArray sortedArrayUsingComparator:^NSComparisonResult(NSString* a, NSString* b) {

        //find the strings that will actually be compared for alphabetical ordering
        NSString* firstStringToCompare = [self stringByRemovingPrecedingThe:a];
        NSString* secondStringToCompare = [self stringByRemovingPrecedingThe:b];

        return [firstStringToCompare compare:secondStringToCompare];
    }];
    return sortedArray;
}

// Remove "the"s, also removes preceding white spaces that are left as a result. Assumes no preceding whitespaces to start with. nb: Trailing white spaces will be deleted too.

-(NSString*) stringByRemovingPrecedingThe:(NSString*) originalString {
    NSString* result;
    if ([[originalString substringToIndex:3].lowercaseString isEqualToString:@"the"]) {
        result = [[originalString substringFromIndex:3] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
    }
    else {
        result = originalString;
    }
    return result;
}
Kin answered 10/2, 2017 at 18:55 Comment(1)
I just looked at this years later, and I realised it should also include "a" and "an". These should be easy to add.Kin
G
1
-(IBAction)SegmentbtnCLK:(id)sender
{ [self sortArryofDictionary];
    [self.objtable reloadData];}
-(void)sortArryofDictionary
{ NSSortDescriptor *sorter;
    switch (sortcontrol.selectedSegmentIndex)
    {case 0:
            sorter=[[NSSortDescriptor alloc]initWithKey:@"Name" ascending:YES];
            break;
        case 1:
            sorter=[[NSSortDescriptor alloc]initWithKey:@"Age" ascending:YES];
            default:
            break; }
    NSArray *sortdiscriptor=[[NSArray alloc]initWithObjects:sorter, nil];
    [arr sortUsingDescriptors:sortdiscriptor];
    }
Gastrula answered 21/2, 2015 at 2:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.