Reputation: 2052
I have a List[Map[String, Any]
and I want to return the map which has a certain value for one of the keys. Here's an obfusticated example:
val items: List[Map[String, Any]] = List(Map("name" -> "A", "size" -> 50), Map("name" -> "B", "size" -> 75), Map("name" -> "C", "size" -> 100)))
val mapB: Map[String, Any] = items.find(|m| m("name") == "B") // Psuedo code
mapB
would be Map("name" -> "B", "size" -> 75)
.
Bonus Question
Is there also a way to return the value of another key instead of the whole Map
?
For example, if I only wanted the size
value (75) for name
B
? I know I can extract it from the Map
as a two-step operation, but if there's another more idiomatic way, I'd be interested in learning it.
Thanks!
Upvotes: 1
Views: 777
Reputation: 51271
find()
returns an Option
in case what you're looking for cannot be found.
val mapB: Option[Map[String, Any]] = items.find(_("name") == "B") //safe
or
val mapB: Map[String, Any] = items.find(_("name") == "B").get //unsafe, might throw
To retrieve the size
value from the first Map
where "name" -> "B"
you could do something like this.
val sz :Any = items.find(m => m.get("name").contains("B")
&& m.get("size").nonEmpty).fold(0:Any)(_("size"))
Note that sz
is type Any
because that's what the type of the Map
values. Which means that you'd have to cast it (discouraged) to type Int
before you can do anything useful with it.
Avoid type Any
. It's a sure sign that you're going in the wrong direction.
Upvotes: 2
Reputation: 22895
Complementing jwvh's answers (and using Tim's suggestion to improve safety).
Here is a function that addresses your bonus question.
def findAndGet(maps: List[Map[String, Any]], condition: (String, Any), key: String): Option[Any] = condition match {
case (k, v) =>
maps.find(map => map.get(k).contains(v)).flatMap(map => map.get(key))
}
findAndGet(maps = items, condition = ("name", "B"), key = "size")
// res0: Option[Any] = Some(75)
BTW, a Map[String, Any]
makes me thing you are dealing with JSONs, have you take a look to any of the Scala libraries for dealing with them in a more "typesafe" way?, having an Any
in your code should always be an alarm that something is wrong.
Upvotes: 1