Scala 在两个映射之间生成更改集
检测两个Scala 在两个映射之间生成更改集,scala,scala-collections,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
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))
}
这里有一个想法。可能需要O(N*logn)和N=max(在.size之前,在.size之后):
作为一种非常普遍的方法,您可能有兴趣了解Wie?像我们的议长穆蒂?SchockThat看起来是对的,但它是
O(N)+O(M*logm)
其中M
是变更集的大小。@RexKerr如果我之前有。foreach
外部(O(N))并在之后调用。获取内部(O(logn)),这已经是O(N*logn),对吗?对于M,您正在使用带有O(logn)
get的映射?然后你可以使用一个排序映射你的其他操作保持相同的顺序,但是你可以在O(N)
中通过迭代来实现。对,我没有注意到hash-map-get是常量:-O
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)