Swift 2 - Splitting an array into a dictionary with keys A to Z

I have an array, for example ["Apple", "Banana", "Blueberry", "Eggplant"]

, and I would like to convert it to a dictionary, for example:

[
    "A" : ["Apple"],
    "B" : ["Banana", "Blueberry"],
    "C" : [],
    "D" : [],
    "E" : ["Eggplant"]
]

      

I am using Swift 2 on Xcode 7 beta 4. Thanks!

+3


source to share


5 answers


Using only Swift 2 objects and methods and with a key for each letter in the alphabet:



let alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".characters.map({ String($0) })

let words = ["Apple", "Banana", "Blueberry", "Eggplant"]

var result = [String:[String]]()

for letter in alphabet {
    result[letter] = []
    let matches = words.filter({ $0.hasPrefix(letter) })
    if !matches.isEmpty {
        for word in matches {
            result[letter]?.append(word)
        }
    }
}

print(result)

      

+7


source


I wrote this in the Xcode playground:



import Foundation

var myArray = ["Apple", "Banana", "Blueberry", "Eggplant"]

var myDictionary : NSMutableDictionary = NSMutableDictionary()

for eachString in myArray as [NSString] {

    let firstCharacter = eachString.substringToIndex(1)

    var arrayForCharacter = myDictionary.objectForKey(firstCharacter) as? NSMutableArray

    if arrayForCharacter == nil
    {
        arrayForCharacter = NSMutableArray()
        myDictionary.setObject(arrayForCharacter!, forKey: firstCharacter)
    }

    arrayForCharacter!.addObject(eachString)
}

for eachCharacter in myDictionary.allKeys
{
    var arrayForCharacter = myDictionary.objectForKey(eachCharacter) as! NSArray

    print("for character \(eachCharacter) the array is \(arrayForCharacter)")
}

      

+4


source


I found this question, helped me to better understand some of the concepts I was thinking about. Here is an alternative approach based on the accepted correct answer that is slightly more concise and where the alphabet is generated programmatically. This is Swift 2 in Xcode 7.

let words = ["Apple", "Banana", "Blueberry", "Eggplant"]
let alphabet = (0..<26).map {n in String(UnicodeScalar("A".unicodeScalars["A".unicodeScalars.startIndex].value + n))}
var results = [String:[String]]()
for letter in alphabet {
    results[letter] = words.filter({$0.hasPrefix(letter)})
}

print(results)

      

I believe but not sure if the string let alphabet

could be more concise.

+3


source


Here is my solution. Works in pure Swift 2 and in O (n) time, where n is the length of the wordlist (and assumes the dictionary is implemented as a hash table).

var dictionary: [String : [String]] = [ "A" : [], "B" : [], "C" : [], "D" : [],
"E" : [], "F" : [] /* etc */ ]

let words = ["Apple", "Banana", "Blueberry", "Eggplant"]

for word in words
{
    let firstLetter = String(word[word.startIndex]).uppercaseString

    if let list = dictionary[firstLetter]
    {
        dictionary[firstLetter] = list + [word]
    }
    else
    {
         print("I'm sorry I can't do that Dave, with \(word)")
    }
}

print("\(dictionary)")

      

+2


source


I just made such a useful array extension that allows you to map an array of objects to a dictionary of indexed object symbols based on a selected property of the object.

    extension Array {

    func toIndexedDictionary(by selector: (Element) -> String) -> [Character : [Element]] {

        var dictionary: [Character : [Element]] = [:]

        for element in self {
            let selector = selector(element)
            guard let firstCharacter = selector.firstCharacter else { continue }

            if let list = dictionary[firstCharacter] {
                dictionary[firstCharacter] = list + [element]
            } else {
                // create list for new character
                dictionary[firstCharacter] = [element]
            }
        }
        return dictionary
    }
}

extension String {
    var firstCharacter : Character? {
        if count > 0 {
            return self[startIndex]
        }
        return nil
    }
}

      

0


source







All Articles