8

親キーのリストがあり、それぞれに 0 個以上の関連値がある可能性があります。どのコレクションを使用すればよいかわかりません。

私は使っているMap[Int,List[String]]

私はマップを次のように宣言しています

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

次に、新しい要素の追加を処理する 2 つの方法があります。1 つ目は新しいキーを追加することaddNodeで、2 つ目は新しい値を追加することです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> 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)

更新 2:

上記のコードの問題は、代わりにnodes += (1->null)キーを関連付ける必要がある行です。Nil以下は作業コードです。

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

3 に答える 3

25

マルチマップの使用

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)

マルチマップなし

別の方法は、不変の値に固執することです。レンズの使用を避けたい場合( scalazを参照)、次のようにノードを追加できます。

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

ここでそれは機能しています(あなたのコメントに応じて):

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

Scalaz の使用

scalaz ライブラリを使用すると、これは単にEmptyパターンを使用しているだけであることがわかります。

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

Mapまたは、モノイドであるという事実を利用できます。

nodes = nodes |+| Map(key -> List(value))
于 2012-05-13T12:45:35.293 に答える
1

@oxbow_lakesの回答に加えて、addMap2つのマップを正しく追加する方法を使用する方法のアイデアを次に示します(つまり、一致するキーのリストを結合し、新しいキーの新しいリストを追加します):

class EnhancedListMap(self: Map[Int,List[String]]) {
  def addMap(other: Map[Int,List[String]]) =
    (this.ungroup ++ enhanceListMap(other).ungroup)
      .groupBy(_._1)
      .mapValues(_.map(_._2))

  def ungroup() =
    self.toList.flatMap{ case (k,vs) => vs.map(k -> _) }
}

implicit def enhanceListMap(self: Map[Int,List[String]]) = new EnhancedListMap(self)

そして、次のように使用します。

val a = Map(1 -> List("a","b"), 2 -> List("c","d"))
val b = Map(2 -> List("e","f"), 3 -> List("g","h"))
a addMap b
//Map(3 -> List(g, h), 1 -> List(a, b), 2 -> List(c, d, e, f))

addNodeaddValue、および(上記addValuesと同じ)を含めることができます。EnhancedListMap

  def addNode(key: Int) =
    if(self contains key) self else self + (key -> Nil)

  def addValue(key: Int, value: String) =
    self + (key -> (value :: (self get key getOrElse Nil)))

  def addValues(key: Int, values: List[String]) =
    self + (key -> (values ::: (self get key getOrElse Nil)))

そして、それらを一緒に使用します:

var nodes = Map.empty[Int, List[String]]             
// Map()
nodes = nodes.addNode(1)                             
// Map(1 -> List())
nodes = nodes.addValue(1,"a")                        
// Map(1 -> List(a))
nodes = nodes.addValue(2,"b")                        
// Map(1 -> List(a), 2 -> List(b))
nodes = nodes.addValues(2,List("c","d"))             
// Map(1 -> List(a), 2 -> List(c, d, b))
nodes = nodes.addValues(3,List("e","f"))             
// Map(1 -> List(a), 2 -> List(c, d, b), 3 -> List(e, f))
nodes = nodes.addMap(Map(3 -> List("g","h"), 4-> List("i","j")))
// Map(1 -> List(a), 2 -> List(c, d, b), 3 -> List(e, f, g, h), 4 -> List(i, j))
于 2012-05-13T14:16:22.497 に答える
0

getOrElseUpdate私は可変マップによって提供される方法がとても好きです:

import scala.collection.mutable._

private val nodes = new HashMap[Int, Buffer[String]]

def addNode(key: Int): Unit =
  nodes.getOrElseUpdate(key, new ArrayBuffer)

def addValue(key: Int, value: String): Unit  =
  nodes.getOrElseUpdate(key, new ArrayBuffer) += value
于 2012-05-13T22:36:04.873 に答える