0

我已经建立了一个这样的抽象:

class Thing(val messages: Map[String, Seq[String]]) { 
  def and(that: Thing): Thing = {
    new Thing(this.messages ++ that.messages)
  }
}

this的地图String -> Seq[String]需要与that的地图合并。

这是我能想到的最好的方法:

def and(that: Thing): Thing = {
  val keys = this.messages.keys ++ that.messages.keys
  val tuples = keys map {
    case key: String =>
      val theseMessages = this.messages.getOrElse(key, Seq[String]())
      val thoseMessages = that.messages.getOrElse(key, Seq[String]())
      (key, theseMessages ++ thoseMessages)
  }
  new Thing(tuples.toMap)
}
4

3 回答 3

3

这是一个使用的版本groupBy

def and(that: Thing): Thing = {
  new Thing(
    (this.messages.toIndexedSeq ++ that.messages)
      .groupBy(_._1)
      .map { case (k,vs) => k -> vs.flatMap(_._2) }
      .toMap)
}
于 2012-10-21T03:37:10.633 回答
1

Scalaz库包含这个函数,即|+|半群附加)运算符。请注意,您需要选择比 更具体的集合类型Seq,即具有半组实例的集合类型,因此我使用了List.

import scalaz._, Scalaz._

class Thing(val messages: Map[String, List[String]]) { 
  def and(that: Thing): Thing =
    new Thing(this.messages |+| that.messages)
}

您还可以为 定义一个半群实例Thing,并使用|+|运算符来组合Things。

case class Thing(val messages: Map[String, List[String]])

implicit val ThingSemigroup = new Semigroup[Thing] {
  def append(t1: Thing, t2: => Thing) = new Thing(t1.messages |+| t2.messages)
}

Thing(Map("foo" -> List("bar"))) |+| Thing(Map("foo" -> List("baz")))
// Thing(Map(foo -> List(bar, baz)))
于 2012-10-21T09:59:23.243 回答
0

我在评论中链接到的答案的更具体、稍微修改的版本可能会使方法更清晰:

def and(that: Thing): Thing = {
  new Thing(this.messages.foldLeft(that.messages) { case (out, (keyToAdd, valuesToAdd)) =>
    out ++ Map(keyToAdd -> out.get(keyToAdd).map(_ ++ valuesToAdd).getOrElse(valuesToAdd))
  })
}

还具有不循环遍历其中一张地图的优点。

于 2012-10-21T03:45:51.077 回答