Search code examples
arraysswiftsortingset

Split and sort string array swift 3


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?


Solution

  • 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.