找出两张地图之间的差异

时间:2018-07-30 15:36:19

标签: scala

我发现了几种方法来查找两个地图之间的键集差异。但是,我想比较完整的key-> values。

我将两个地图设置为Map[String, Map[String, String]]

所以如果我有两张地图

var source = Map(
  "one" -> Map("a" -> "bbb", "b" -> "qww"),
  "two" -> Map("b" -> "ccc")
)

var target = Map(
  "one" -> Map("a" -> "bbb", "b" -> "qqq", "c" -> "ccc"),
  "two" -> Map("b" -> "ccc")
)

我想做类似source - target

的事情

获得

的最终输出
 Map("one" -> Map("b" -> "qww")

我只关心确保所有sourcetarget匹配(因此在示例中,target("one")("c")是无关紧要的)。我想知道是否可以执行一些漂亮的单行函数来完成此任务,否则,我总是可以回过头来遍历所有函数并手动进行比较。

编辑代码更新-

var differences = new ListBuffer[(String, String)]()
source.foreach{
  case (db, tableMap) =>
    tableMap.foreach{
      case (table, createTable) =>
        if(createTable != target(db)(table)){
          differences.append((db, table))
        }
    }
}

2 个答案:

答案 0 :(得分:1)

鉴于您的要求,source diff target(如列表所示)会很好用。通过使用diff从两个外部Map遍历foldLeft列表,对源和目标之间的内部Map再次对每个键应用diff会生成想要的净内部Map:

val source = Map(
  "one" -> Map("a" -> "bbb", "b" -> "qww"),
  "two" -> Map("b" -> "ccc"),
  "three" -> Map("c" -> "xxx")
)

val target = Map(
  "one" -> Map("a" -> "bbb", "b" -> "qqq", "c" -> "ccc"),
  "two" -> Map("b" -> "ccc"),
  "four" -> Map("d" -> "yyy")
)

(source.toList diff target.toList).
  foldLeft( Map[String, Map[String,String]]() ){ (acc, x) =>
    val corrTargMap = target.getOrElse(x._1, Map[String, String]())
    val mapDiff = (x._2.toList diff corrTargMap.toList).toMap
    acc + (x._1 -> mapDiff)
  }
// res1: scala.collection.immutable.Map[String,Map[String,String]] =
//   Map(one -> Map(b -> qww), three -> Map(c -> xxx))

答案 1 :(得分:0)

这有效(没有toListtoMap等转换):

s.map{case (x,y)=>(x,y.filter(p=>t.getOrElse(x,Map()).forall(_!=p)))}.filter(_._2!=Map())

在Scala REPL中:

scala> val s = Map(
     |   "one" -> Map("a" -> "bbb", "b" -> "qww"),
     |   "two" -> Map("b" -> "ccc"),
     |   "three" -> Map("c" -> "xxx")
     | )
s: scala.collection.immutable.Map[String,scala.collection.immutable.Map[String,String]] = Map(one -> Map(a -> bbb, b ->
 qww), two -> Map(b -> ccc), three -> Map(c -> xxx))

scala> val t = Map(
     |   "one" -> Map("a" -> "bbb", "b" -> "qqq", "c" -> "ccc"),
     |   "two" -> Map("b" -> "ccc"),
     |   "four" -> Map("d" -> "yyy")
     | )
t: scala.collection.immutable.Map[String,scala.collection.immutable.Map[String,String]] = Map(one -> Map(a -> bbb, b ->
 qqq, c -> ccc), two -> Map(b -> ccc), four -> Map(d -> yyy))

scala> s.map{case (x,y)=>(x,y.filter(p=>t.getOrElse(x,Map()).forall(_!=p)))}.filter(_._2!=Map())
res2: scala.collection.immutable.Map[String,scala.collection.immutable.Map[String,String]] = Map(one -> Map(b -> qww), three
 -> Map(c -> xxx))