Sort array in Swift Ascending with empty items
Asked Answered
D

3

7

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?

Doghouse answered 25/10, 2014 at 20:21 Comment(4)
Not sure what you mean by "I found I couldn't add a value to my array if I did not declare like a 100 items". Do you mean you cannot append items to the array?Ignoramus
And your code sorts the elements in descending order (as also mentioned in the title). This would order the empty strings last. Your example output does not match the code.Magyar
@Ignoramus No, what I want is an array that I can add values to and delete values from. Ideally this array would only contain the values and no empty items, so it would only be as long as needed at any time. If I need to add a value, I would need a new item in the array. I just chose to give it 100 items with value "" so I would always have space for a new value. Do you know what I mean?Doghouse
@MartinR Yes, you are correct. I copied the wrong part, sorry. I have updated my original post.Doghouse
C
11

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", "", "", ""]
Crinkle answered 25/10, 2014 at 21:20 Comment(3)
Thank you. The last part for sorting the array ascending with the empty items at the end did solve my question, that is why I chose this as the solution. Thank you everyone (especially @Antonio) for the other options and documentation!Doghouse
@Bastiaan You're welcome. But, based on what it seems you need, I would highly recommend using either @Antonio's Dictionary method or NSMutableSet instead of pre-populating an Array with empty strings; it'll be much more efficient.Crinkle
I understand and I will definitely look into and try to convert my program to using a dictionary like Antonio's or your NSMutableSet suggestionDoghouse
I
2

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 }
Ignoramus answered 25/10, 2014 at 20:52 Comment(8)
I need to add and delete items from my array. The user inputs names one after another and they need to be stored in an array, then that array needs to be sorted and the contents of the array is displayed in a UITextView. I want to use an array without empty spaces for that but still be able to manipulate the array completely.Doghouse
You can remove an item from the dictionary by setting the value for a key to nil, for example persons["Clair"] = nilIgnoramus
yes but I still need to add new persons to the database.Doghouse
I don't understand what the problem is. What's wrong with persons["Clair"] = true?Ignoramus
The user for instance inputs a new name 'Pete' and that needs to be stored as well. I am sorry if I don't understand what you mean, the whole concept of a dictionary is new to me and I am still learning Swift ...Doghouse
If you want to develop in swift efficiently, I suggest you to learn more about dictionaries. By the way, I've updated my answer, take a lookIgnoramus
@Bastiaan persons["Pete"] = true adds to the Dictionary, persons["Pete"] = nil removes it from the Dictionary. With those methods you can add and remove any items you need.Crinkle
@MikeS Thanks! Now I understand the operations for using a dictionary, thanks Antonio as well!Doghouse
R
2

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)
Raised answered 25/10, 2014 at 22:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.