如何在scala中将嵌套映射[string,string]作为点分隔的键和值字符串

Posted

技术标签:

【中文标题】如何在scala中将嵌套映射[string,string]作为点分隔的键和值字符串【英文标题】:How to make a nested map[string,string] as dot separated strings of key and value in scala 【发布时间】:2020-10-02 22:50:03 【问题描述】:

我有一个 Map[String, String]。

编辑: val m: Map[String, Any] = Map("a" -> Map("b" -> Map("c" -> "e", "d" -> "g")))

有没有办法将我的 Map[String,Any] 转换为 Map[String,String]

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

Map("a.b.c" -> "e", "a.b.d" -> "g")

我找到了一个用于 Map[String,Int] 的早期解决方案。链接在这里给出: How to make a nested map as dot separated strings of key and value in scala

我尝试更改代码(在上述问题的 cmets 中给出):

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


traverse(m)

但是,我收到以下错误: Scrutinee 与模式类型不兼容,发现:Map[String, String],必填:String

我是 Scala 新手,所以无法修改代码,请指出是什么原因造成的。

更新解决方案:

def unravel(badmap :Map[String,_]
          ,key:List[String] = Nil) :Map[String,String] =
badmap.foldLeft(Map.empty[String,String])
  case (m,(k,v)) if v.isInstanceOf[Map[_,_]] =>
    println("Case1" + m)
    m ++ unravel(v.asInstanceOf[Map[String,_]], k::key)
  case (m,(k,v)) =>
    println("Case2: " + m)
    val tempv = if (v!=null) v.toString  else null
    m + ((k::key).reverse.mkString(".") -> tempv )

我有一个空值导致它失败。我更新了给出的解决方案。谢谢!

【问题讨论】:

case m: Map[String, Any] 是您需要为模式匹配保留的内容。 所以,我必须将我的 Map[String, String] 更改为 Map[String,Any]? 示例地图打印为 Map(a -> Map(b -> Map(c -> e, d -> g)))。我需要将其更改为 a.b.c -> e @jwvh 嗨,我已经做出改变了 Map[String, Any] 闻起来像 json,您最好使用更好的工具来处理此类数据类型。 【参考方案1】:

你在一个糟糕的地方(输入Any)。

有时我们不得不使用不明智和不安全的工具(运行时类型转换)来摆脱糟糕的情况。

def unravel(badmap :Map[String,_]
           ,key:List[String] = Nil) :Map[String,String] =
  badmap.foldLeft(Map.empty[String,String])
    case (m,(k,v)) if v.isInstanceOf[Map[_,_]] =>
      m ++ unravel(v.asInstanceOf[Map[String,_]], k::key)
    case (m,(k,v)) =>
      m + ((k::key).reverse.mkString(".") -> v.toString)
  

测试:

val m: Map[String, _] =
  Map("a" -> Map("b" -> Map("c" -> "e", "d" -> "g")))

unravel(m)
//res0: Map[String,String] = Map(a.b.c -> e, a.b.d -> g)

最好避免这种情况。返回并修复生成 Map 的代码。

【讨论】:

快速怀疑。现在如果我的代码返回 Map[String,_] 这个问题会更有效吗?如果是,你能告诉我同样的解开功能是否仍然有效? 所以,上面我给出了一个示例地图。我打印的实际地图是这样的: Map(keyA -> Map(keyB -> valB, keyC -> keyC, keyD -> Map(keyE -> valE, keyF -> valF), keyG -> null)) 地图是 Map[String,_] 类型。当我在上面运行 unravel 函数时,我得到空指针异常。

以上是关于如何在scala中将嵌套映射[string,string]作为点分隔的键和值字符串的主要内容,如果未能解决你的问题,请参考以下文章

Scala Play:如何使用重复值和嵌套值呈现表单映射?

如何在 scala 中将 RDD[(int, string)] 转换为 Dataframe

如何在 Spring Boot 中将嵌套的 JSON 对象映射为 SQL 表行

在scala中将spark决策树模型调试字符串转换为嵌套JSON

Scala 中的嵌套默认映射

如何取消嵌套具有以下类型的 spark rdd ((String, scala.collection.immutable.Map[String,scala.collection.immutable.M