Scala系列,单键多重值 [英] Scala collections, single key multiple values

查看:129
本文介绍了Scala系列,单键多重值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个父密钥列表,每个密钥可能有零个或多个相关联的值。我不确定要使用哪个集合。



我正在使用 Map [Int,List [String]] / p>

我宣布地图为

  var nodes = new HashMap [ Int,List [String]] 

然后我有两种方法来处理添加新元素。第一个是添加新密钥 addNode ,第二个是添加新值 addValue 。最初,密钥不会有与之相关的任何值。后来,在执行期间,新值将被关联。

  def addNode(key:Int)= nodes + =(key  - >)

def addValue(key:Int,value:String)= ???

我不知道如何实现 addValues



更新:



为了回应@ oxbow-lakes答案,这是我收到的错误。请注意,密钥不需要与其相关联的值。

  scala> var nodes = Map.empty [Int,List [String]] 
nodes:scala.collection.immutable.Map [Int,List [String]] = Map()

scala>节点+ =(1-> null)

scala> node + =(1 - >(one::(nodes get 1 getOrElse Nil)))
java.lang.NullPointerException
at。< init>(< console>:9) $&$ {$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $
at $ print(< console>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
在java.lang.reflect.Method.invoke(Method.java:597)
at scala.tools.nsc.interpreter .IMain $ ReadEvalPrint.call(IMain.scala:704)
at scala.tools.nsc.interpreter.IMain $ Request $$ anonfun $ 14.apply(IMain.scala:920)
at scala.tools .nsc.interpreter.Line $$ anonfun $ 1.apply $ mcV $ sp(Line.scala:43)
at scala.tools.nsc.io.package $$ anon $ 2.run(package.scala:25)
在java.lang.Thread.run(Thread.java :680)



更新2:



上述代码的问题是 nodes + =(1-> null)的关键字应该与 Nil 而不是。以下是工作代码。

  scala> var nodes = Map.empty [Int,List [String]] 
nodes:scala.collection.immutable.Map [Int,List [String]] = Map()

scala>节点+ =(1> Nil)

scala> nodes + =(1 - >(one::(nodes get 1 getOrElse Nil)))

scala>节点
res27:scala.collection.immutable.Map [Int,List [String]] = Map(1 - > List(one))


解决方案

使用MultiMap



您可能想使用 MultiMap ,这是一个与 Map [K,Set [V]] 同构的可变集合。使用如下:

  import collection.mutable 
val mm = new mutable.HashMap [Int,mutable.Set [ String]] with mutable.MultiMap [Int,String]

然后添加您的节点:

  mm addBinding(key,value)



没有MultiMap



另一种选择是坚持不变的值。假设您希望避免使用镜头(请参阅 scalaz ),可以按如下方式添加节点:

  nodes + =(key  - >(value ::(nodes get key getOrElse Nil)))
pre>

这里正在工作(响应您的评论):

 阶> var nodes = Map.empty [Int,List [String]] 
nodes:scala.collection.immutable.Map [Int,List [String]] = Map()

scala> def addNode(key:Int,value:String)=
| node + =(key - >(value ::(nodes get key getOrElse Nil)))
addNode:(key:Int,value:String)单位

scala> addNode(1,嗨)

scala> addNode(1,Bye)

scala>节点
res2:scala.collection.immutable.Map [Int,List [String]] = Map(1 - > List(Bye,Hi))



使用Scalaz



使用scalaz库,您可以意识到这只是使用 pattern:

  nodes + =(key  - >(value ::〜节点获取密钥)))

或者您可以利用地图单一

  nodes = nodes | + |地图(键 - >列表(值))


I have a list of parent keys, each of which could possibly have zero or more associated values. I am not sure which collection to use.

I am using Map[Int,List[String]]

I am declaring the Map as

var nodes = new HashMap[Int, List[String]]

Then I have two methods to handle adding new elements. The first is to add new keys addNode and the second is to add new values addValue. Initially, the key will not have any values associated with it. Later on, during execution, new values will be associated.

def addNode(key: Int) = nodes += (key -> "")

def addValue(key: Int, value: String) = ???

I am not sure how to implement addValues

Update:

In response to @oxbow-lakes answer, This is the error I am receiving. Please note that keys need not have values associated with them.

scala> var nodes = Map.empty[Int, List[String]]
nodes: scala.collection.immutable.Map[Int,List[String]] = Map()

scala> nodes += (1->null)

scala> nodes += (1 -> ("one" :: (nodes get 1 getOrElse Nil)))
java.lang.NullPointerException
    at .<init>(<console>:9)
    at .<clinit>(<console>)
    at .<init>(<console>:11)
    at .<clinit>(<console>)
    at $print(<console>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:704)
    at scala.tools.nsc.interpreter.IMain$Request$$anonfun$14.apply(IMain.scala:920)
    at scala.tools.nsc.interpreter.Line$$anonfun$1.apply$mcV$sp(Line.scala:43)
    at scala.tools.nsc.io.package$$anon$2.run(package.scala:25)
    at java.lang.Thread.run(Thread.java:680)

Update 2:

The problem with the code above is the line nodes += (1->null) the key should be associated with Nil instead. Below is the working code.

scala> var nodes = Map.empty[Int, List[String]]
nodes: scala.collection.immutable.Map[Int,List[String]] = Map()

scala> nodes += (1->Nil)

scala> nodes += (1 -> ("one" :: (nodes get 1 getOrElse Nil)))

scala> nodes
res27: scala.collection.immutable.Map[Int,List[String]] = Map(1 -> List(one))

解决方案

Using MultiMap

You possibly want to use MultiMap, which is a mutable collection isomorphic to Map[K, Set[V]]. Use as follows:

import collection.mutable
val mm = new mutable.HashMap[Int, mutable.Set[String]] with mutable.MultiMap[Int, String]

Then you add your nodes:

mm addBinding (key, value)

Without MultiMap

The alternative is to stick with immutable values. Assuming you want to avoid using lenses (see scalaz), you can add nodes as follows:

nodes += (key -> (value :: (nodes get key getOrElse Nil)))

Here it is working (in response to your comment):

scala> var nodes = Map.empty[Int, List[String]]
nodes: scala.collection.immutable.Map[Int,List[String]] = Map()

scala> def addNode(key: Int, value: String) =
     | nodes += (key -> (value :: (nodes get key getOrElse Nil)))
addNode: (key: Int, value: String)Unit

scala> addNode(1, "Hi")

scala> addNode(1, "Bye")

scala> nodes
res2: scala.collection.immutable.Map[Int,List[String]] = Map(1 -> List(Bye, Hi))

Using Scalaz

Using the scalaz library, you can realize that this is simply using the Empty pattern:

nodes += (key -> (value :: ~(nodes get key)))

Or you could take advantage of the fact that Map is a monoid:

nodes = nodes |+| Map(key -> List(value))

这篇关于Scala系列,单键多重值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆