【问题标题】:How to make a nested map as dot separated strings of key and value in scala如何在scala中将嵌套映射作为点分隔的键和值字符串
【发布时间】:2018-02-27 06:56:23
【问题描述】:

我有一个Map[String, Any]。该值可以是另一个Map 等等。

val m: Map[String, Any] = Map("a" -> Map("b" -> Map("c" -> 1, "d" -> 4)))

将这个嵌套的Map 转换为另一个具有类似值的Map 的最佳方法是什么

Map("a.b.c" -> 1, "a.b.d" -> 4)

【问题讨论】:

  • 实现的时候发生了什么?
  • 我对 scala 很陌生。所以,我无法实现它。
  • 嗯,你试过了吗?

标签: scala scala-collections


【解决方案1】:

只需像在任何其他编程语言中一样使用递归(它不是 Scala 特有的)。

val m: Map[String, Any] = Map("a" -> Map("b" -> Map("c" -> 1, "d" -> 4)))

def traverse(el: Any, acc: List[String] = List.empty[String]): Map[String, Int] = el match {
  case leaf: Int => Map(acc.reverse.mkString(".") -> leaf)
  case m: Map[String, Any] => m flatMap {
    case (k, v) => traverse(v, k :: acc)
  }
}

traverse(m)

res2_2: Map[String, Int] = Map("a.b.c" -> 1, "a.b.d" -> 4)

顺便说一句,

1) 提出的解决方案不是尾递归的(因此可能会在非常深的树上引发堆栈溢出) - 您可以编写尾递归版本作为练习。提示 - 你需要一个累加器来收集结果(或者使用可变缓冲区,idn,也许你不是真正的函数式编程,并且被雇主强迫使用 Scala :))。

2) List 不适合累加器的结构(因为 performance 的结构),我只是懒得使用不太常见的结构,因为你懒得尝试至少以某种方式实现这个微不足道的算法。我敢打赌应该有一个关于 SO 的重复问题,但又懒得去寻找它:)。

3) @unchecked 注释适用于我代码中的某个位置(猜猜在哪里?)。还有模式匹配的默认情况(您可以构建一个测试用例来破坏我的功能以找出原因)。

【讨论】:

    猜你喜欢
    • 2020-10-02
    • 1970-01-01
    • 2019-12-06
    • 1970-01-01
    • 1970-01-01
    • 2015-03-19
    • 1970-01-01
    • 1970-01-01
    • 2020-03-23
    相关资源
    最近更新 更多