Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
类似于Python字典的适当Scala集合_Scala - Fatal编程技术网

类似于Python字典的适当Scala集合

类似于Python字典的适当Scala集合,scala,Scala,我有一个迭代返回(键,值)的算法。我要做的是将这些结果存储在一个结构中,这样,如果键不存在,它将添加它和相应的值。现在,如果键存在,它将把值附加到现有的值数组中 在python中,我可以使用以下格式的python字典来实现这一点: dict = {'key1': [val1, val2, val3], 'key2': [val4, val5], 'key3': [val6], ... } 简单地做: if key in dict.keys(): dic

我有一个迭代返回
(键,值)
的算法。我要做的是将这些结果存储在一个结构中,这样,如果
不存在,它将添加它和相应的
。现在,如果键存在,它将把
附加到现有的值数组中

在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中做到这一点?

可能是这样的

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

或者,结合Sergey非常好的建议:

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

由于Scala中强大的typesystem,您可以以更通用的方式执行此操作:

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

另一个
insert
implementation
m+(k->(m.getOrElse(k,List()):+v))
?@jwvh,这个方法每次调用时都会创建一个新映射吗?@johntitutusjungao,是的。但是Scala集合的实现成本很低(它们是持久的,请参阅)。它们在不同版本之间共享大部分结构。Scala也有可变集合,因此如果愿意的话,可以模仿Python方法。Scala的“风格”是使用不可变的。FP首选项是不可变的数据结构,根据需要创建并在放弃时销毁(垃圾收集)。