Словарь init (группировка: по :), 2 уровня - упрощение кода - PullRequest
0 голосов
/ 07 ноября 2019

Dictionary(init(grouping:by:)) отлично работает, когда мне нужно сгруппировать элементы массива по какому-либо свойству.

Что я получаю:

{
    key1: [
        value1,
        value2,
        value3
        ],
    key2: [
        value4,
        value5,
        value6
        ]
}

Однако мне нужно преобразовать массив дальше, группируякаждое разбиение на более мелкие группы, чтобы полученная структура данных имела два слоя:

{
    key1: {
        anotherKey1: [
            value1,
            ],
        anotherKey2: [
            value2,
            value3]
    },
    key1: {
        anotherKey3: [
            value4,
            ],
        anotherKey4: [
            value5,
            value6]
    },
}

Какой самый простой способ достижения этого результата? В настоящее время я должен перебрать результат 1-го вызова инициализатора словаря:

        let grouped = Dictionary(grouping: Array(source), by: {$0.key1)
        var grouped2 = [KeyType1 : [KeyType2? : [ValueType]]]()

        for pair in grouped {
            if let key = pair.key {
                grouped2[key] = Dictionary(grouping: pair.value, by: {$0.key1})
            }
        }


        print(grouped2)

И это дает мне именно тот результат, который я хочу: двухуровневый словарь массивов.

Но я подозреваю, что есть более простой способ достижения того же результата, без необходимости вручную обрабатывать каждую пару ключ / значение.

1 Ответ

2 голосов
/ 07 ноября 2019

Вы можете сделать это, выполнив вызов init(grouping:by:), а затем вызов mapValues, который дополнительно отображает каждую "группу" в другой словарь. И этот словарь будет снова создан с помощью init(grouping:by:), используя второй ключ группировки.

т.е.

let grouped = Dictionary(grouping: source, by: firstKey)
    .mapValues { Dictionary(grouping: $0, by: secondKey) }

Например, сначала сгруппировать группу чисел по их % 2 значения, затем их % 4 значения:

let source = [1,2,3,4,5,6,7,8,9,10,11,12,13]
let grouped = Dictionary(grouping: source, by: { $0 % 2 })
    .mapValues { Dictionary.init(grouping: $0, by: { $0 % 4 }) }
print(grouped)
...