Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 260
B_s Avatar asked Oct 25 '14 20:10

B_s


2 Answers

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", "", "", ""]
like image 90
Mike S Avatar answered Sep 19 '22 14:09

Mike S


Reading comments in your question and other answers, I realize that you need a ordered set, containing unique values. There's no built in data structure in swift for that, but it can be easily be done by using a dictionary: simply use the string value as dictionary key, and a boolean as dictionary value - this ensures that keys are unique:

var persons = [String : Bool]()

persons["Bert"] = true
persons["Daniel"] = true
persons["Clair"] = true
persons["Clair"] = true
persons["Aaron"] = true
persons["Daniel"] = true
persons["Clair"] = true

You can quickly verify that with the above code the dictionary contains 4 elements only.

Next, obtain a copy of the dictionary keys (as an array):

var values = persons.keys.array

and sort it:

values.sort { $0.localizedCaseInsensitiveCompare($1) == NSComparisonResult.OrderedAscending }

Alternatively, if you want to stick with the fixed sized array, you can remove the empty items before sorting:

persons = persons
            .filter( { $0.isEmpty == false } )
            .sorted {$0.localizedCaseInsensitiveCompare($1) == NSComparisonResult.OrderedAscending }
like image 35
Antonio Avatar answered Sep 17 '22 14:09

Antonio