2016-05-13 12 views
0

私は反復的に返します(key, value)を返すアルゴリズムがあります。私がしたいことは、keyが存在しない場合は、それを追加し、それに対応するvalueを追加するような構造にこれらの結果を格納することです。現在、キーが存在する場合、既存の値の配列にvalueを追加します。適切なScalaのコレクションは、Pythonの辞書に似て

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

を単に実行します:Pythonで

、私はこのフォーマットでPythonの辞書を使ってこれを行うことができます

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)) 

あるいは、セルゲイの非常に細かい提案を組み込む:あなたは、より一般的な方法でこれを行うことができますので、Scalaでは、強力な型システムの

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、このメソッドは呼び出されるたびに新しいマップを作成しますか? – 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)))