Swift: Sort Array in Alphabetical Order

16,066

Solution 1

What about a nice Quicksort function to order your array of Strings? (Source)

First create an Array extension to decompose the given array:

extension Array {
  var decompose : (head: T, tail: [T])? {
    return (count > 0) ? (self[0], Array(self[1..<count])) : nil
  }
}

Second create the Quicksort function so you can order the decomposed Array:

func qsort(input: [String]) -> [String] {
  if let (pivot, rest) = input.decompose {
    let lesser = rest.filter { $0 < pivot }
    let greater = rest.filter { $0 >= pivot }
    return qsort(lesser) + [pivot] + qsort(greater)
  } else {
    return []
  }
}

Declare the variables with explicit type (Dictionary and Array):

var partsOfNovel = [​String​ : [String]]()
var partsSectionTitles = [String]()

Fill them:

partsOfNovel = [
  "Part 1" : ["Chapter X:1", "Chapter X:2", "Chapter X:3"],
  "Part 2" : ["Chapter X:1", "Chapter X:2"],
  "Part 3" : ["Chapter X:1"]
]

partsSectionTitles = partsOfNovel.allKeys
// ["Part 1", "Part 3", "Part 2"]

And finally order your Strings Array:

var orderedSectionTitles = qsort(partsSectionTitles)
// ["Part 1", "Part 2", "Part 3"]

I think is a nice solution in pure Swift, I hope it helps!

Solution 2

This should meet your need. The array contains String element.

var partsSectionTitles:[String] = partsOfNovel.allKeys as [String]
var sortedNames = partsSectionTitles.sorted { $0.localizedCaseInsensitiveCompare($1) == NSComparisonResult.OrderedDescending }

Solution 3

let array = ["j","d","k","h","m"]
func backward(x : String, y: String) -> Bool
{
    return x>y
}

var reverse = sorted(array,backward)


println((reverse))

or you can write like :

var newrev = sorted(array, {$0 < $1})

or

var other = sorted (array , >)

Solution 4

Let's say you have the following Objective-C code with NSDictionary and NSArray:

NSDictionary *partsOfNovel = @{@"Part 1" : @[@"Chapter X:1", @"Chapter X:2", @"Chapter X:3"],
                               @"Part 4" : @[@"Chapter X:1", @"Chapter X:2"],
                               @"Part 3" : @[@"Chapter X:1"]};

NSArray *partsSectionTitles = [[partsOfNovel allKeys] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
NSLog(@"%@", partsSectionTitles);

With this code, your console will print:

"Part 1",
"Part 3",
"Part 4"

With Swift, you can get the keys of a Dictionary and put them in a Array like this:

let partsOfNovel = [
    "Part 1" : ["Chapter X:1", "Chapter X:2", "Chapter X:3"],
    "Part 4" : ["Chapter X:1", "Chapter X:2"],
    "Part 3" : ["Chapter X:1"]]

let nonOrderedPartsSectionTitles = partsOfNovel.keys.array

You can then apply a sort on this Array and print the result like this:

let partsSectionTitles = nonOrderedPartsSectionTitles.sorted { $0.localizedCaseInsensitiveCompare($1) == NSComparisonResult.OrderedAscending }
println(partsSectionTitles) //[Part 1, Part 3, Part 4]

But all of this can be done with Swift in a much concise way (tested with Playground):

let partsOfNovel = [
    "Part 1" : ["Chapter X:1", "Chapter X:2", "Chapter X:3"],
    "Part 4" : ["Chapter X:1", "Chapter X:2"],
    "Part 3" : ["Chapter X:1"]]

let partsSectionTitles = partsOfNovel.keys.array.sorted { $0.0 < $1.0 }
println(partsSectionTitles) //[Part 1, Part 3, Part 4]
Share:
16,066
Admin
Author by

Admin

Updated on June 04, 2022

Comments

  • Admin
    Admin almost 2 years

    I'm very new at Swift and Objective-C.

    I have a table view controller in which I have declared a dictionary and an array:

    var parts = [:]
    var partsSectionTitles: NSArray!
    

    In my viewDidLoad function, I have:

    parts = [
            "Part 1" : ["X:1", "X:2", "X:3"],
            "Part 2" : ["X:1", "X:2"],
            "Part 3" : ["X:1"]
        ]
    
    var partsSectionTitles = parts.allKeys
    

    I've already successfully completed this table view controller in Objective-C, and in order to sort the partsSectionTitles alphabetically, I used:

    partsSectionTitles = [[parts allKeys] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
    

    So, my question is: How do I write the preceding Objective-C code in Swift? Thank you in advance for your answers.

    UPDATE: I was able to solve the problem using bits and pieces from the answers you guys provided. So, thank you! Here's what I have:

    I declared the parts dictionary as:

    var parts = [String:[String]]()
    

    which allowed me to provide multiple values to each key. This was a HUGE help.

    Then I was able to create the partsSectionTitles and sort it:

    partsSectionTitles = [String](parts.keys)
    partsSectionTitles.sort(){ $0 < $1 }
    

    This worked as I received no errors.

    • Lance
      Lance over 9 years
      You were down voted for not posting what you had tried. I'm sure you have tried several things. Post what you've got so far and we can help you fix it up :)
    • Lance
      Lance over 9 years
      If by chance you haven't tried anything, take a look at Swifts global Sort function. You can pass partsOfNovel.keys to that along with a closure to do the sorting.
    • David Gomez
      David Gomez over 9 years
      The Swift's Sorted function is an easy way to do it, and you can find an explanation at the Swift's Book from Apple. Closures
    • Admin
      Admin over 9 years
      Yeah, I tried a few things that I cannot remember at the moment. I'll try to post what I tried the next time I ask a question. The down vote was unnecessary, but thanks... I guess.
  • Imanou Petit
    Imanou Petit over 9 years
    var partsSectionTitles:[String] = partsOfNovel.allKeys as [String] doesn't compile for me. I get the following error message: '[String : Array<String>]' does not have a member named 'allKeys'.
  • gabbler
    gabbler over 9 years
    You can use is NSDictionary(dictionary: partsOfNovel).allKeys for casting, OP's code has var partsOfNovel = [:].
  • Imanou Petit
    Imanou Petit over 9 years
    partsOfNovel should be declared as of type [​String​ : [String]], not as of type [​String​ : String].
  • David Gomez
    David Gomez over 9 years
    Yes you could make it that way to be completely sure, but in this case the compiler infers correctly that you are sending an array of strins. But I agree is nicer.
  • Admin
    Admin over 9 years
    Hello, Thank you for your answer. I only used part of it, but it worked: partsSectionTitles.sort(){ $0 < $1 } I also changed the partsOfNovel declaration to: var partsOfNovel = [String:[String]]() Thanks again!
  • Admin
    Admin over 9 years
    Hello, Thank you for your answer. I only used part of it, but it worked: var partsOfNovel = [String:[String]]() I also changed the partsOfNovel declaration to: partsSectionTitles.sort(){ $0 < $1 } Thanks again!
  • robert
    robert about 6 years
    With Swift 4, use ... { $0.localizedCaseInsensitiveCompare($1) == ComparisonResult.orderedDescending }