如何使用scala删除重复键并合并列表的其他键值?

时间:2014-10-21 13:49:18

标签: list scala

我正在将List [JSONObject]结构作为某些代码段的输出 -

List(List({
"groupName": "group1",
"maxSeverity": -1,
"hostCount": 3,
"members": [
    "192.168.20.11",
    "192.168.20.52",
    "192.168.20.53"
]
}),
List(),
List({
"groupName": "group1",
"maxSeverity": -1,
"hostCount": 2,
"members": [
    "192.168.20.20",
    "192.168.20.52"
]
}))

我想合并整个输出以形成一个包含的列表 - 1)组名

2)严重性 - 从所有列表元素中最小化

3)hostcout - 从所有列表元素中添加hostcount

4)成员 - 类似的数组,没有来自所有列表元素的重复值。

所以输出有点像这样 -

List({
"groupName": "group1",
"maxSeverity": -1,
"hostCount": 5,
"members": [
    "192.168.20.11",
    "192.168.20.52",
    "192.168.20.53",
    "192.168.20.20",
    "192.168.20.52"
]
})

如何将整个列表合并到一个列表中以获得上述输出???

2 个答案:

答案 0 :(得分:1)

考虑使用Jackson将这些解析为案例类,然后以这种方式处理数据。

object JsonMerge {
  import com.fasterxml.jackson.databind.ObjectMapper
  import com.fasterxml.jackson.module.scala.DefaultScalaModule
  import com.fasterxml.jackson.module.scala.experimental.ScalaObjectMapper

  case class ServerGroup(groupName: String, hostCount: Int, maxSeverity: Int, members: Iterable[String])

  def collapseGroup(groups: List[ServerGroup]): ServerGroup = {
    val members = groups.flatMap(_.members).toSet
    ServerGroup(groups.head.groupName, members.size, groups.map(_.maxSeverity).min, members)
  }

  def main(args: Array[String]) {
    val objectMapper = new ObjectMapper with ScalaObjectMapper
    objectMapper.registerModule(DefaultScalaModule)

    val allGroups = objectMapper.readValue[List[ServerGroup]](rawData)
    val output = allGroups.groupBy(_.groupName).values.map(collapseGroup)
    objectMapper.writerWithDefaultPrettyPrinter().writeValue(System.out, output)
  }

  val rawData = """
[{
  "groupName": "group1",
  "hostCount": 3,
  "maxSeverity": -1,
  "members": [
    "192.168.20.11",
    "192.168.20.52",
    "192.168.20.53"
  ]
},{
  "groupName": "group1",
  "hostCount": 2,
  "maxSeverity": -1,
  "members": [
    "192.168.20.20",
    "192.168.20.52"
  ]
},{
  "groupName": "group2",
  "hostCount": 1,
  "maxSeverity": 2,
  "members": [
    "192.168.20.52"
  ]
}]"""

}

这有这个输出:

[ {
  "groupName" : "group2",
  "hostCount" : 1,
  "maxSeverity" : 2,
  "members" : [ "192.168.20.52" ]
}, {
  "groupName" : "group1",
  "hostCount" : 4,
  "maxSeverity" : -1,
  "members" : [ "192.168.20.11", "192.168.20.52", "192.168.20.53", "192.168.20.20" ]
} ]

答案 1 :(得分:0)

这是您可能需要的:

代码

object JsonMerge {

  def main(args: Array[String]) {
    val l1 = List(List(
      JSON.parseFull(
        """
      {
"groupName": "group1",
"maxSeverity": -1,
"hostCount": 3,
"members": [
    "192.168.20.11",
    "192.168.20.52",
    "192.168.20.53"
]
}
      """).get.asInstanceOf[Map[String, Any]]),
      List(),
      List(
        JSON.parseFull("""
    {
"groupName": "group1",
"maxSeverity": -1,
"hostCount": 2,
"members": [
    "192.168.20.20",
    "192.168.20.52"
]
}
    """).get.asInstanceOf[Map[String, Any]]),
      List(
        JSON.parseFull("""
    {
"groupName": "group2",
"maxSeverity": 2,
"hostCount": 1,
"members": [
    "192.168.20.52"
]
}
    """).get.asInstanceOf[Map[String, Any]])).flatten

    //    println(l1)
    //    println(l1.groupBy(_("groupName")))

    val minimumSeverity = -1

    val mergedList = l1.groupBy(_("groupName")).map { grouped =>

      val folded = grouped._2.foldLeft(Map[String, Any]("maxSeverity" -> minimumSeverity)) { (current, next) =>
        val severity1 = current.get("maxSeverity").map(s => s match {
          case v: Int => v
          case _ => minimumSeverity
        }).getOrElse(minimumSeverity)

        val severity2 = current.get("maxSeverity").map(s => s match {
          case v: Int => v
          case _ => minimumSeverity
        }).getOrElse(minimumSeverity)

        val severity = Math.max(severity1, severity2)

        val m1 = current.get("members").map(n => n match {
          case l: List[_] => l
          case _ => List()
        }).getOrElse(List()).toSet

        val m2 = next.get("members").map(n => n match {
          case l: List[_] => l
          case _ => List()
        }).getOrElse(List()).toSet

        val members = m1 union m2

        Map("maxSeverity" -> severity,
          "hostCount" -> members.size,
          "members" -> members.toList)
      }

      folded + ("groupName" -> grouped._1)
    }

    mergedList foreach println

  }

}

输出

Map(maxSeverity -> -1, hostCount -> 1, members -> List(192.168.20.52), groupName -> group2)
Map(maxSeverity -> -1, hostCount -> 4, members -> List(192.168.20.11, 192.168.20.52, 192.168.20.53, 192.168.20.20), groupName -> group1)