生成两个地图之间的变更集

时间:2014-07-04 20:20:38

标签: scala scala-collections

检测两个Map实例之间的更改的最佳/最干净/最有效的方法是什么。即。

val before = Map(1 -> "foo", 2 -> "bar", 3 -> "baz")
val after  = Map(1 -> "baz", 2 -> "bar", 4 -> "boo")

// not pretty:
val removed = before.keySet diff after.keySet
val added   = after.filterNot { case (key, _) => before contains key }
val changed = (before.keySet intersect after.keySet).flatMap { key =>
  val a = before(key)
  val b = after (key)
  if (a == b) None else Some(key -> (a, b))
}

1 个答案:

答案 0 :(得分:1)

这是一个想法。它可能需要O(N * log N),其中N = max(before.size,after.size):

sealed trait Change[+K, +V]
case class Removed[K   ](key: K)                      extends Change[K, Nothing]
case class Added  [K, V](key: K, value : V)           extends Change[K, V]
case class Updated[K, V](key: K, before: V, after: V) extends Change[K, V]

def changes[K, V](before: Map[K, V], after: Map[K, V]): Iterable[Change[K, V]] ={
  val b = Iterable.newBuilder[Change[K, V]]
  before.foreach { case (k, vb) =>
    after.get(k) match {
      case Some(va) if vb != va => b += Updated(k, vb, va)
      case None                 => b += Removed(k)
      case _ =>
    }
  }
  after.foreach { case (k, va) =>
    if (!before.contains(k)) b += Added(k, va)
  }
  b.result()
}

changes(before, after).foreach(println)

// Updated(1,foo,baz)
// Removed(3)
// Added(4,boo)