sharingiscaring
sharingiscaring

Reputation: 165

How to filter List of Maps in Scala

My list of Maps is like below

val myMap=  List(
    Map("name" -> "1st" , "status" -> "0"),
    Map("name" -> "2nd" , "status" -> "1"),
    Map("name" -> "3rd" , "status" -> "1")
  )

I am trying to filter the list based on "status" = "1" and get another List of Maps with only name

So the output should be

Map("name" -> "2nd"),
Map("name" -> "3rd")

I am a beginner in scala, understand that I need to apply map,filter. But not getting how to proceed here.

Upvotes: 0

Views: 966

Answers (3)

Leo C
Leo C

Reputation: 22439

Consider combining filter & map into collect:

val myMap = List(
    Map("name" -> "1st", "status" -> "0"),
    Map("name" -> "2nd", "status" -> "1"),
    Map("name" -> "3rd", "status" -> "1"),
    Map("xx" -> "4th",   "status" -> "1"),
    Map("name" -> "5th", "yy" -> "1")
  )

myMap.collect{ case m if m.get("status").contains("1") && m.get("name").nonEmpty =>
    Map("name" -> m("name"))
}
// List(Map(name -> 2nd), Map(name -> 3rd))

The guard clause in collect ensures that only those Maps consisting of key-value status->1 as well as key name will be included.

Upvotes: 1

Tim
Tim

Reputation: 27356

If you are doing both filter and map the best solution is often to use collect:

myMap.collect{ case m if m.get("status").contains("1") => m - "status" }

Upvotes: 1

Harald Gliebe
Harald Gliebe

Reputation: 7564

With filter and map you can write is as follows

myMap
  .filter(m => m.get("status") == Some("1")) // filter maps with status 1
  .map(m => "name" -> m.get("name").get)     // use the name attribute to create a new map

Note that the get method returns an Option since the requested key might not exist. Therefore you need to compare with Some("1") and also use the .get on the result of m.get("name"). Using the .get method without checking that the option is not empty is not a good style, since this will fail at runtime if the map doesn't contain a name key. A better approach which would omit these maps from the result could be

myMap
  .filter(m => m.get("status") == Some("1"))
  .flatMap(m => m.get("name").map(n => "name" -> n))

The map used here is from the Option class and will map a found name to Some("name" -> n) and None to None. The flatMap will finally unpack the Some and ignore the None elments

Upvotes: 0

Related Questions