如何在Scala中访问嵌套映射中的键值

Posted

技术标签:

【中文标题】如何在Scala中访问嵌套映射中的键值【英文标题】:how to access key values within nested map in Scala 【发布时间】:2019-12-06 08:28:25 【问题描述】:

我有一个地图列表。其中一张地图里面有另一张地图(2 级深)。我需要从最里面的地图访问一些键,最后更改值。我面临的问题是从最里面的地图中检索键。我对 Scala 很陌生,但没有运气就尝试了不同的东西。

我已将 List 展平为 Map,然后尝试检索键值。问题是,我可以打印整个内部地图,但不知道如何迭代。

下面是代码:在一个非常基本的情况下,我想从最里面的地图中检索与键对应的值;说钥匙"isStudentLoankRequested""schoolStructure"

object ListToMaps 
  def main(args: Array[String]) 
    val dataInputKeysListvar = List(Map("identityKeyName" -> "MY_ID", "identityKeyValue" -> "abcd-1234-xyz"),
          Map("identityKeyName" -> "OUR_ID", "identityKeyValue" -> "1234567890",
            "identityInformation" -> Map("writeFrequency" -> "NEVER", "studentStatus" -> "SEP", "annualValue" -> 0,
            "schoolStructure" -> "OTHER", "studentType" -> "FTS", "occupationDescription" -> "other",
            "studentAccountBalanceRange" -> "string", "isStudentLoankRequested" -> "N", "schoolName" -> "myschool",
            "parentsIncome" -> 100)),
          Map("identityKeyName" -> "FINAL_DECISION_KEY", "identityKeyValue" -> "0000-ABCD-4567-IJKL"))

        val x = dataInputKeysListvar.flatten.toMap
        val y = x("identityInformation")

    if (x.contains("identityInformation"))
      println("value of y is" + y)
    
  

正如您从 print stmt 中看到的,我可以打印最内层地图的整个地图,但在迭代方面需要帮助。

【问题讨论】:

你到底需要用那个内部地图做什么?你累过什么没用,为什么没用? 需要更改一些值。例如,将“isStudentLoankRequested”->“N”改为“isStudentLoankRequested”->“NO”。 内部映射是可变的还是不可变的?如果是第二个,您想对更改后的地图做什么,在外部地图和列表上更新它?更改的逻辑是静态的还是动态的,例如某些输入表示字段而其他输入表示新值? 两者都是不可变的。我想更改值并传递给另一个程序。这是因为下游程序期望参数为“NO”(字符串)而不是“N”(布尔) 如果你有一个Map[String, Object] 并且你想修改地图中的值,使用可变地图可能比常规地图更容易。 【参考方案1】:

如果您在编译时知道需要更改哪些字段和值。 您可以对逻辑进行硬编码,如下所示:

def fixData(data: List[Map[String, Any]]): List[Map[String, Any]] =
  data.map  outerMap =>
    outerMap.get("identityInformation") match 
      case Some(innerMap) =>
        // Put as many key pairs you want to change.
        // Note: if the key does not exists it will be added!
        val updatedInnerMap = innerMap.asInstanceOf[Map[String, String]] ++ Map(
          "isStudentLoankRequested" -> "No"
        )
        outerMap + ("identityInformation" -> updatedInnerMap)

      case None =>
        outerMap
    
  

如果要更改的键值是动态的,和/或某些内部键可能不存在,或者嵌套级别可以继续。 你可以这样做:

def updateMap(map: Map[String, Any], updates: Map[String, Any]): Map[String, Any] =
  map.map 
    case (key, value: Map[_, _]) =>
      updates.get(key) match 
        case Some(innerUpdates : Map[_, _]) =>
          key -> updateMap(
            map = value.asInstanceOf[Map[String, Any]],
            updates = innerUpdates.asInstanceOf[Map[String, Any]]
          )

        case Some(newValue) =>
          key -> newValue

        case None =>
          key -> value
      

    case (key, value) =>
      key -> updates.getOrElse(key, default = value)
  


def fixData(data: List[Map[String, Any]], updates: Map[String, Any]): List[Map[String, Any]] =
  data.map(outerMap => updateMap(outerMap, updates))

注意:上面的 sn-ps 使用了像 asInstanceOf 这样的“不安全”技术,因为在你得到 Map[String, Any] 的那一刻我们就失去了类型安全性。每次看到这样的结构,我都会想到 JSON。我建议您使用适当的库来管理此类数据,例如circe,而不是像上面那样编写代码。

【讨论】:

以上是关于如何在Scala中访问嵌套映射中的键值的主要内容,如果未能解决你的问题,请参考以下文章

如何在嵌套字典中查找所有出现的键,同时跟踪外部字典键值?

如何在 scala 中生成的键值对中添加值

如何在 Laravel 中获取嵌套的键值

如何在 D3 中检索嵌套数据集的键值

如何使用 snakeYaml 库访问 YAML 文件中的内部(嵌套)键值

如果在树中嵌套其他值,则获取文本文件(yaml)中的键值[重复]