【问题标题】:Scala - Flatten a List of Maps to MapScala - 将地图列表展平为地图
【发布时间】:2020-07-06 13:51:42
【问题描述】:

我需要将键映射到 Scala 列表中的映射。也就是说,我需要从这里出发:

  Map(k1 -> List(Map(k2 -> v2)))

得到这个:

  Map(k1 -> Map(k2 -> v2))

这个东西正在工作,但我正在寻找更有效的东西。

  val m1 = Map("k1" -> List(Map("k2" -> "v2")))
  val m2 = m1("k1").flatten.toMap
  val m3 = Map("k1" -> m2)

有什么想法吗?

提前致谢。

【问题讨论】:

  • 如果列表有多个地图会怎样?密钥保证永远不会相同吗?如果不是,重复项应该怎么办?
  • 这不会发生,列表中总是只有一张地图。是的,它们永远不会相同。
  • m1.view.mapValues(_.head).toMap 应该可以解决问题。但是,您似乎正在处理一些类似 JSON 的数据,我建议您查看任何优秀的 scala 库。此外,您知道列表总是只有一个元素这一事实似乎是一个设计错误,那为什么它是一个列表呢?
  • 是的,你确实是对的。我刚刚发布了一个新问题,包括更多详细信息,如果您想查看它:stackoverflow.com/questions/60860141/…。不过,您的回答适合这个特定的问题,所以我决定创建一个新帖子。谢谢!

标签: scala


【解决方案1】:

就像@Luis Miguel Mejía Suárez 所说的那样,主要是这样的

val maps = Map(k1 -> List(Map(k2 -> v2)))
def flattenMaps[K, V]: List[Map[K, V]] => Map[K, V] = ???
maps.mapValues(flattenMaps).toMap

问题在于你的扁平化逻辑的细节:

// assumes that list always of size 1, loses random elements if bigger, blows up if size=0
def flattenMaps[K, V]: List[Map[K, V]] => Map[K, V] = _.head

// last wins
def flattenMaps[K, V]: List[Map[K, V]] => Map[K, V] = _.foldLeft(Map.empty[K, V]) {
  (bigMap, map) => bigMap ++ map
}

// first wins
def flattenMaps[K, V]: List[Map[K, V]] => Map[K, V] = _.foldLeft(Map.empty[K, V]) {
  (bigMap, map) => map ++ bigMap
}

// if you want to optimize for some reason, you can use builder instead
def flattenMaps[K, V]: List[Map[K, V]] => Map[K, V] = _.foldLeft(Map.newBuilder[K, V]) {
  (builder, map) =>
     builder ++= map
     builder
}.result

// or basically any other logic that makes sense and is defined for any input that type-checks

您应该定义一些正确的行为,以防您的列表包含多个(或没有)元素,否则如果您忘记您的假设,有一天您可能会感到惊讶。

【讨论】:

    猜你喜欢
    • 2017-07-30
    • 2020-07-06
    • 1970-01-01
    • 2015-04-18
    • 2020-08-10
    • 2012-01-07
    • 2015-07-10
    • 2014-10-26
    • 2019-04-01
    相关资源
    最近更新 更多