2016-05-13 69 views
0

我有一個算法,返回迭代返回(key, value)。我想要做的就是將這些結果存儲在一個結構中,如果key不存在,它會將其添加到相應的value中。現在,如果密鑰存在,它會將value附加到現有值的數組。適當的斯卡拉集合類似於Python字典

在Python中,我可以使用Python字典這種格式做到這一點:

dict = {'key1': [val1, val2, val3], 
     'key2': [val4, val5], 
     'key3': [val6], ... } 

,只是做:

if key in dict.keys(): 
    dict[key].append(value) 
else: 
    dict[key] = [value] 

如何做到這一點的Scala呢?

回答

1

也許是這樣的?

scala> def insert[K,V](k: K, v: V, m: Map[K, List[V]]): Map[K, List[V]] = { 
    | if (m contains k) m + (k -> (m(k) :+ v)) 
    | else m + (k -> List(v)) } 
insert: [K, V](k: K, v: V, m: Map[K,List[V]])Map[K,List[V]] 

scala> insert('b', 23, Map('b' -> List(2))) 
res30: Map[Char,List[Int]] = Map(b -> List(2, 23)) 

scala> insert('b', 23, Map('c' -> List(2))) 
res31: Map[Char,List[Int]] = Map(c -> List(2), b -> List(23)) 

或者,結合謝爾蓋的很細的建議:因爲在斯卡拉強大的類型系統的

def insert[K,V](k: K, v: V, m: Map[K, List[V]]): Map[K, List[V]] = 
    m + (k -> (m.getOrElse(k, List()) :+ v)) 
+1

另一個'insert'實現'm +(k - >(m.getOrElse(k,List()):+ v))'? –

+0

@SergeyLagutin,我同意。簡潔明瞭。 – jwvh

+0

@jwvh,這種方法每次調用時都會創建一個新的Map嗎? – jtitusj

0

,你可以在一個更一般的方式做到這一點:

import scalaz._, Scalaz._ 

case class CollectingMap[K, V, C[_]](underlying: Map[K, C[V]] = Map[K, C[V]]()) { 
    def add(key: K, value: V)(implicit s: Monoid[C[V]], a: Applicative[C]): CollectingMap[K, V, C] = { 
    // Either get the old value from the underyling map or the empty collection, provided by the Monoid[C[V]] 
    val oldValue = underlying.get(key).getOrElse(mzero[C[V]]) 
    // Append the old vlaue to the new value, provided by Monoid |+|. 
    // value.point[C] is provided by the Applicative, which allows us to lift the value into the collection C. 
    val newValue = oldValue |+| value.point[C] 
    // return the updated value, wrapped into CollectingMap again. 
    CollectingMap(underlying.updated(key, newValue)) 
    } 
} 

例如:

val m = CollectingMap[Int, String, List]() 
m.add(2, "bar").add(2, "foo") 
// => res4: CollectingMap[Int,String,List] = CollectingMap(Map(2 -> List(bar, foo)))