Scala 合并地图列表

Scala merge list of maps

输入=

val data = List(
    Map("id" -> "123", "name" -> "raju", 
        "sub" -> List(Map("id" -> "english", "status" -> 2))), 
    Map("id" -> "123", "name" -> "raju", 
        "sub" -> List(Map("id" -> "english", "status" -> 0), 
                      Map("id" -> "hindi", "status" -> 0))))

预期输出:

val data = List(
    Map("id" -> "123", "name" -> "raju",
        "sub" -> List(Map("id" -> "english", "status" -> 2),
                      Map("id" -> "hindi", "status" -> 1),
                      Map("id" -> "english", "status" -> 0),
                      Map("id" -> "hindi", "status" -> 0))))

我试图在不删除旧键的情况下将“子”键值合并到列表中,但我无法获取它。任何人都可以使用 scala 帮助解决这个问题。

首先创建一些案例 类。使用这些比使用地图更容易。

case class Person(id: String, name: String, sub: List[Language]) 

case class Language(id: String, status: Int)

现在,创建 Person 的列表:

val data = List(
    Person("123", "raju", List(Language("english", 2))),
    Person("123", "raju", List(Language("english", 0), Language("hindi", 0))))

我不知道您的合并逻辑是什么,但假设您只想连接具有相同 ID 的人的 sub-列表。你可以这样做:

// Gets a map from ID to the list of persons with that ID
data.groupBy(_.id)

// Gets a List[List[Person]] (the values of the map)
.values

// Makes a new Person out of the inner list of persons, concatenating all the languages of that person.
.map(persons => Person(
    persons.head.id,
    persons.head.name, 
    persons.flatMap(_.sub)))

这里是一个像你的例子一样在纯 Maps/Lists 上工作的例子。

val data = List(
    Map("id" -> "123", "name" -> "raju", 
        "sub" -> List(Map("id" -> "english", "status" -> 2))), 
    Map("id" -> "123", "name" -> "raju", 
        "sub" -> List(Map("id" -> "english", "status" -> 0), 
                      Map("id" -> "hindi", "status" -> 0))))
                      
val expected = List(
    Map("id" -> "123", "name" -> "raju",
        "sub" -> List(Map("id" -> "english", "status" -> 2),
                      Map("id" -> "hindi", "status" -> 1),
                      Map("id" -> "english", "status" -> 0),
                      Map("id" -> "hindi", "status" -> 0))))
                      
val res = data.groupBy(x => (x.get("id"), x.get("name"))).collect { case (_, items) => 
  items.reduceLeft { (l, r) =>
    l.updated("sub", l("sub").asInstanceOf[List[_]] ++ r("sub").asInstanceOf[List[_]])
  }
}

println(res)

https://scalafiddle.io/sf/FBj4Mvi/0

PS:老实说,创建​​类型化结构(正如其他人所建议的那样)可能仍然是更好的解决方案。