2017-01-10 7 views
0

Скажем, у меня есть карта ключей для массивов значений и хотите добавить значение в одной из этих массивов:Как добавить значения в массив, хранящийся на карте?

func addVal<K:Hashable, V>(map: inout [K: [V]], new: (key: K, val: V)) { 
    if var list = map[new.key] { 
     list.append(new.val) 
    } else { 
     map[new.key] = [new.val] 
    } 
} 

Этот код не будет работать: поскольку массивы имеют семантику значений, list является копией map[new.key], и новое значение никогда не будет вставлено в сохраненный массив.

Есть ли хороший, идиоматический путь к этому?

Я знаю, что это работает отлично:

func addVal<K:Hashable, V>(map: inout [K: [V]], new: (key: K, val: V)) { 
    if map[new.key] != nil { 
     map[new.key].append(new.val) 
    } else { 
     map[new.key] = [new.val] 
    } 
} 

Я считаю, что это не-приятный обходной путь, хотя; Я бы предпочел иметь дело с опциями, не проверяя явно для nil.

+0

Использование контекста: [группировать массивы] (http://stackoverflow.com/questions/41564580/ групповые элементы-оф-ан-массива-на-какой-недвижимости/41566988 # 41566988). – Raphael

+1

Если вы не хотите, чтобы массив был скопирован, см. Http://stackoverflow.com/questions/41079687/dictionary-in-swift-with-mutable-array-as-value-is-performing-very-slow -как. Основываясь на вашем примере использования, см. Также http://stackoverflow.com/questions/31220002/how-to-group-by-the-elements-of-an-array-in-swift – Hamish

ответ

1

Это безопасно, не возиться с nil, и избегает ненужного копирования управляющего воздействия массива:

func addVal<K:Hashable, V>(map: inout [K: [V]], new: (key: K, val: V)) { 
    if let _ = map[new.key] { 
     map[new.key]!.append(new.val) 
    } else { 
     map[new.key] = [new.val] 
    } 
} 
+0

Это очень крутое решение! – Raphael

+0

Обратите внимание: я верю, что это все равно вызовет копию мутированного массива из-за того, что 'map [new.key] !. append (new.val)' создаст временную переменную массива (теперь и словарь, и словарь временная переменная имеет вид на массив), добавьте к этому (вызывая копирование при записи), а затем вставьте его обратно в словарь. См. Q & A, с которым я связан выше, чтобы избежать этого копирования. – Hamish

+0

@Hamish Это можно избежать без прямого редактирования объекта, прошедшего через функцию? Кажется, что это будет иметь место для всех inout переменных. –