我有一个迭代返回(key, value)
的算法。我想要做的是将这些结果存储在一个结构中,如果key
不存在,它将添加它和相应的value
。现在,如果密钥存在,它会将value
附加到现有的值数组。
在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中执行此操作?
答案 0 :(得分: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 :(得分:0)
由于Scala中强大的类型系统,您可以以更一般的方式执行此操作:
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)))