Search code examples
arraysxcodesortingswiftalphabetical

Sort array in Swift Ascending with empty items


In Xcode (Swift) I have an array that is initialized to 100 empty items:

var persons = [String](count:100, repeatedValue: "")

With some functions I add content to the places in the array, starting at 0.

So for example my array is at some given moment:

["Bert", "Daniel", "Claire", "Aaron", "", "", ... ""]

With the dots representing the rest of the empty items. I use this function for sorting my array alphabetically:

persons = persons.sorted {$0.localizedCaseInsensitiveCompare($1) == NSComparisonResult.OrderedAscending }

This gives me an array back like this:

["", "", ... , "Aaron", "Bert", "Claire", "Daniel"]

What I want is to sort my array alphabetically but not with the empty items at the front. I need to get an array back like:

["Aaron", "Bert", "Claire", "Daniel", "", "", ... , ""]

For my part, I do not want an array with empty items but I found I couldn't add a value to my array if I did not declare like a 100 items (the array won't be filled to a 100 items, that's for sure).

Can anyone help me out?


Solution

  • As @Antonio said, it looks like you need a descending order set of strings. Besides the Dictionary method in @Antonio's answer (which works great), you can also use NSMutableSet (bridged from Objective-C):

    let personSet = NSMutableSet()
    personSet.addObject("Aaron")
    personSet.addObject("Daniel")
    personSet.addObject("Claire")
    personSet.addObject("Aaron")
    personSet.addObject("Bert")
    personSet.addObject("Bert")
    personSet.addObject("Joe")
    personSet.removeObject("Joe") // You can remove too of course
    

    Which creates the set:

    {(
        Claire,
        Aaron,
        Daniel,
        Bert
    )}
    

    Then, when you want the people as an Array, you can use the allObjects cast to a [String]:

    personSet.allObjects as [String]
    

    And you can sort it just like you're currently doing:

    let people = (personSet.allObjects as [String]).sort {$0.localizedCaseInsensitiveCompare($1) == NSComparisonResult.OrderedAscending }
    

    Which makes people:

    [Aaron, Bert, Claire, Daniel]
    

    For those wondering how to sort the Array as originally stated in the question (Ascending but with empty strings at the end), that can be done with a little bit of custom logic in the sort function:

    var persons = ["Bert", "Daniel", "Claire", "Aaron", "", "", ""]
    persons.sort { (a, b) -> Bool in
        if a.isEmpty {
            return false
        } else if b.isEmpty {
            return true
        } else {
            return a.localizedCaseInsensitiveCompare(b) == .OrderedAscending
        }
    }
    

    Result:

    ["Aaron", "Bert", "Claire", "Daniel", "", "", ""]