我已经构建了一个这样的抽象:
class Thing(val messages: Map[String, Seq[String]]) {
def and(that: Thing): Thing = {
new Thing(this.messages ++ that.messages)
}
}
this
的{{1}}地图需要与String -> Seq[String]
地图合并。
这是我能想到的最佳方式:
that
答案 0 :(得分: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)
}
答案 1 :(得分: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
定义半群实例,并使用|+|
运算符组合Thing
。
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)))
答案 2 :(得分: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))
})
}
还具有不在其中一个地图上循环的优势。