In Clojure the diff function can be applied to maps, that doesn't seem to be the case in Scala, is anyone aware of something in Scala that would make it more accessible to obtain what the Clojure diff function obtains when it is applied to maps?

Here's the Clojure diff function explained for reference.

http://clojuredocs.org/clojure_core/clojure.data/diff

有帮助吗?

解决方案 2

As others have said there isn't something exactly like that, but you can build it anyways. Here's my attempt that is added on as a companion to the map class. It produces the same result as the clojure diff example.

object MapsDemo extends App{
  implicit class MapCompanionOps[A,B](val a: Map[A,B]) extends AnyVal {
    def diff(b: Map[A,B]): (Map[A,B],Map[A,B],Map[A,B]) = {
          (a.filter(p => !b.exists(_ == p)),  //things-only-in-a
           b.filter(p => !a.exists(_ == p)),    //things-only-in-b
           a.flatMap(p => b.find(_ == p) ))    //things-in-both
        }
  }

    val uno = Map("same" ->"same","different" -> "one")
    val dos = Map("same" ->"same","different" -> "two","onlyhere"->"whatever")
    println(uno diff dos) //(Map(different -> one),Map(different -> two, onlyhere -> whatever),Map(same -> same))
    println( Map("a"->1).diff(Map("a"->1,"b"->2)) ) //(Map(),Map(b -> 2),Map(a -> 1))
}

其他提示

This is equivalent to Clojure's diff:

import collection.generic.CanBuildFrom

def diff[T, Col](x: Col with TraversableOnce[T], y: Col with TraversableOnce[T])
        (implicit cbf: CanBuildFrom[Col, T, Col]): (Col, Col, Col) = {
  val xs = x.toSet
  val ys = y.toSet
  def convert(s: Set[T]) = (cbf(x) ++= s).result
  (convert(xs diff ys), convert(ys diff xs), convert(xs intersect ys))
}

It can operate on any kind of TraversableOnce and will return results with the same type as its parameters:

scala> diff(Map(1 -> 2), Map(1 -> 2))
res35: (scala.collection.immutable.Map[Int,Int], scala.collection.immutable.Map[Int,Int], scala.collection.immutable.Map[Int,Int]) = (Map(),Map(),Map(1 -> 2))

You can achieve that by converting the maps to list first. For example:

scala> val a = Map(1->2, 2-> 3).toList
scala> val b = Map(1->2, 3-> 4).toList
scala> val closureDiff = List(a.diff(b), b.diff(a), a.intersect(b))
closureDiff: List[List[(Int, Int)]] = List(List((2,3)), List((3,4)), List((1,2)))

There is no function in the standard library that doe exactly what you need. However, an un-optimized version can be implemented easily in this manner(sorry for "span" mistake at first try).

def diffffK,V:(Map[K,V],Map[K,V],Map[K,V]) = {

val (both,left) = m1.partition({case (k,v) => m2.get(k)  == Some(v) })
val right = m2.filter({case (k,v) => both.get(k)  != Some(v) })
(both,left,right)

}

also, a map can be converted to a set with a single operator(toSet) and then you can use intercept, union and diff operators of Set.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top