0

I have a List of Maps. One of the maps has another map inside it (2 level deep). I need to access some of keys from the inner most map and finally change the values. The issue I'm facing is to retrieve the keys from the inner most map. I'm very new to Scala and tried different things without luck.

I have flatten the List to Map and then tried to retrieve the key, values. The thing is, I can print the entire inner map, but not sure how to iterate thru that.

Below is the code: at a very basic, I would like to retrieve the values corresponding to keys from innermost map; say for the keys "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)
    }
  }
}

As you can see from the print stmt, I can print the entire map of the inner most map, but need help in terms of iterating thru that.

7
  • What exactly do you need to do with that inner map? What have you tired that did not worked, why it didn't worked? Commented Jul 29, 2019 at 1:55
  • need to change some of the values. As for example, change "isStudentLoankRequested" -> "N" to "isStudentLoankRequested" -> "NO". Commented Jul 29, 2019 at 1:57
  • Is the inner map mutable or immutable? If the second, what do you want to do with the changed map, updated it on the outer Map and on the List? Is the logic about the change static or dynamic, like some input says the field and other the new value? Commented Jul 29, 2019 at 2:00
  • both are immutable. I would like to change the values and pass on to another program. This is because the downstream program expects the argument as "NO" (String) as opposed to "N" (Boolean) Commented Jul 29, 2019 at 2:10
  • 1
    If you have a Map[String, Object] and you wanna modify the values in the map, it is probably easier to use mutable Map instead of regular map. Commented Jul 29, 2019 at 3:58

1 Answer 1

1

If you know at compile time which fields and values you need to change.
You can hard code the logic, like this:

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
    }
  }

If the key-values to change are dynamic, and / or some inner keys may not exists, or if the level of nesting can go on.
You can do something like this:

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))

Note: The above snippets use "unsafe" techniques like asInstanceOf because we lost type safety the moment you got a Map[String, Any]. Always that I see such structure, I think of JSON. I would suggest you to use an appropriate library for managing such kind of data, like circe, instead of writing code as the above.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.