2

I'm looking for the most efficient way to go about this. Say there's an array of objects, mapped out in alphabetical order by names:

let objectArray = [AnyObject]()
let abcNameObjectArray = ["Amy", "Bernadette", "Brian", "Chris", "Candice"]

How would I access all the values in this array that have "A" , "B", or "C" based on the first character of each String value in abcNameObject array, in alphabetical order? I'm trying to unload data and return a specific number of rows in the UITableView's cellForRowAt method and numberOfRowsInSection method based on the number of friends one might have in alphabetical order. The goal is to split the array into a SET of arrays to populate a table view like the Contacts app and ALSO ACCESS the values for a given section. Perhaps utilizing a dictionary might be better to solve this?

12
  • 1
    Possible duplicate of Sorting of an array alphabetically in swift Commented Jul 6, 2017 at 21:59
  • If it is already sorted, then what are you trying to do? Why dont you iterate through array and create an array of dictionaries with key as "A" and value as array of members? there is nothing to sort here. just keep adding elements to this array inside dictionary in the order you find them. Commented Jul 6, 2017 at 22:01
  • You need to edit your question with the desired results given your input. It's not clear what you expect here. Commented Jul 6, 2017 at 22:25
  • I need to unload the sorted array into a UITableView with multiple sections. There'd be a UITableView with 26 sections (# of letters in the alphabet) with n number of rows for each section... @rmaddy Commented Jul 6, 2017 at 22:34
  • 1
    @JoshuaChoi As I said, edit your question. Don't make people read all of the comments to understand your question. Commented Jul 6, 2017 at 22:36

2 Answers 2

2

Solution 1:

Posting my comment as answer with code. Check if this will work for you. You can use sections from first array printed below(store dict.keys.sorted() into some array) and use that as key for displaying cells in that section.

let abcNameObjectArray = ["Amy", "Bernadette", "Brian", "Chris", "Candice", ""]

let dict = abcNameObjectArray.reduce([String: [String]]()) { (key, value) -> [String: [String]] in
    var key = key
    if let first = value.characters.first {
        let prefix = String(describing: first).lowercased()
        var array = key[prefix]
        
        if array == nil {
            array = []
        }
        array!.append(value)
        key[prefix] = array!.sorted()
    }
    return key
}

print(dict.keys.sorted())
print(dict)

Output:

["a", "b", "c"]

["b": ["Bernadette", "Brian"], "a": ["Amy"], "c": ["Candice", "Chris"]]

Solution 2:

Here is one more solution using array of arrays as suggested by rmaddy

let abcNameObjectArray = ["Amy", "Bernadette", "Brian", "Chris", "Candice", ""]
let unicodeScalarA = UnicodeScalar("a")!

var arrayOfArrays = abcNameObjectArray.reduce([[String]]()) { (output, value) -> [[String]] in
    var output = output
    
    if output.count < 26 {
        output = (1..<27).map{ _ in return []}
    }
    
    if let first = value.characters.first {
        let prefix = String(describing: first).lowercased()
        let prefixIndex = Int(UnicodeScalar(prefix)!.value - unicodeScalarA.value)
        var array = output[prefixIndex]
        array.append(value)
        output[prefixIndex] = array.sorted()
    }
    return output
}

arrayOfArrays = arrayOfArrays.filter { $0.count > 0}
print(arrayOfArrays)

Output:

[["Amy"], ["Bernadette", "Brian"], ["Chris", "Candice"]]

You can have number of sections as count of this array and each member will give number of cells required in that section.

Sign up to request clarification or add additional context in comments.

2 Comments

Sorry I haven't been able to respond, but I think your solution is the best one yet so I'm going to mark this as the answer. But, is there a way to modify the output to return an array of Objects, as opposed to an array of Strings?
Thanks for accepting. Yes, you can return anything. This is just an example. You can modify reduce method as shown above and make it to return array of objects. Please feel free to try it out and then ask question if you are unable to do it. We can help you.
0

A Set is not a good choice for the data source for a table view. A Dictionary is not a good choice either. Both are unordered collections, and a table view's data source needs a definite order. I suggest breaking the source array into an array of arrays, where each sub-array contains all the words that begin with a specific letter, sorted in alphabetical order. The code do that might look like this:

import UIKit

let strings = ["arf",
               "woofing",
               "flounder",
               "Manbaby",
               "Dogs",
               "baseballs",
               "Suet",
               "Cards",
               "Tiny-fingered, cheeto-faced, ferret-wearing sh*tgibbon",
               "apple",
               "Acorn",
               "Achy-breaky heart",
               "songbirds",
               "Aces"]

let aValue = "a".unicodeScalars.first!.value
let zValue = "z".unicodeScalars.first!.value


var result = [[String]]()
for value in aValue...zValue {
  let aChar = Character(UnicodeScalar(value)!)
  let thisArray = strings
    .filter{$0.lowercased().characters.first! == aChar}
    .sorted{$0.caseInsensitiveCompare($1) == .orderedAscending}
  if !thisArray.isEmpty {
    result.append(thisArray)
  }
}

result.forEach{print($0)}

That yields the following output:

["Aces", "Achy-breaky heart", "Acorn", "apple", "arf"]
["baseballs"]
["Cards"]
["Dogs"]
["flounder"]
["Manbaby"]
["songbirds", "Suet"]
["Tiny-fingered, cheeto-faced, ferret-wearing sh*tgibbon"]
["woofing"]

If you want an array with an entry for every letter, even when there are no words beginning with that letter, get rid of the if !thisArray.isEmpty test.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.