B_s
B_s

Reputation: 3036

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?

Upvotes: 7

Views: 7588

Answers (3)

CuriousRabbit
CuriousRabbit

Reputation: 2221

I think you are confused about arrays. Swift arrays are not statically allocated structures which must be allocated and filled to maximum design capacity. Below is a crude example of how you can accomplish most of what you are expressing here. However, I really think that a dictionary is better suited to your needs.

var persons = [String]()
var inputData = ["Bert", "Daniel", "Bert", "Claire", "Aaron"]
for item in inputData {
    var found = false
    for existing in persons {
        if existing == item {
            found = true
            break
        }
    }
    if (!found) {
         persons.append(item)
    }
}
persons.sort{$0.localizedCaseInsensitiveCompare($1) == NSComparisonResult.OrderedAscending }
println(persons)

Upvotes: 2

Mike S
Mike S

Reputation: 42335

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", "", "", ""]

Upvotes: 11

Antonio
Antonio

Reputation: 72770

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 }

Upvotes: 2

Related Questions