Group array and get count of occurrences

Hi,

I would like to group a list of alphabets and get a dictionary containing the number of times of each alphabet has occurred.

I could loop through and build the dictionary, just wondering if there was a better way.

let list = ["a", "b", "c", "d", "a", "c"]

Expected Output:
["d": 1, "c": 2, "b": 1, "a": 2]

Attempt so far:
let grouped = Dictionary(grouping: list, by: { $0 }) //This gives the array not the count

Just managed to find on the swift blog:

let grouped = Dictionary(grouping: list, by: { $0 }).mapValues { items in items.count }

Question:
Just wondering would it be 2 iterations ? Is there a better way ?

Thanks to the Dictionary Blog:
So sorry I should have read the swift blog on Dictionary more thoroughly, clearly explains the above situation.

Reference: Transforming a Dictionary’s Values

Further down in the chapter you linked you will find what you are looking for:

let list = ["a", "b", "c", "d", "a", "c"]
var grouped: [String: Int] = [:]
for item in list {
    grouped[item, default: 0] += 1
}

You can also do it in a more functional way:

let list = ["a", "b", "c", "d", "a", "c"]
let grouped = list.reduce(into: [:]) { result, character in 
    result[character, default: 0] += 1 
}
4 Likes

This is awesome, thank you so much !!!!

Just wanna throw-in, I tend to use this

let list = ["a", "b", "c", "d", "a", "c"]
let ones = repeatElement(1, count: list.count)
let counted = Dictionary(zip(list, ones), uniquingKeysWith: +)

// ["c": 2, "b": 1, "a": 2, "d": 1]
6 Likes

+1 for creativity! Cool

Hey cool!

And for sequences there is no need to count the list:

extension Dictionary where Value == Int {

    init<S: Sequence>(counted list: S) where S.Element == Key {
        let ones = repeatElement(1, count: Int.max)
        try! self.init(zip(list, ones), uniquingKeysWith: +)
    }
}

let list = ["a", "b", "c", "d", "a", "c"]
let counted = Dictionary(counted: list)
2 Likes

Thank you so much guys, really nice solutions.