Search code examples
scalahashmap

scala map get the value by key with key case insensitive


I have a map of Map[String, Info], it contains keys which can be either uppercase or lowercase, like this:

person1: PersonInfo1
person2: PersonInfo2
PERSON1: PersonInfo1

i want to get the value for key 'person1', if nothing found I'll try with key of 'PERSON1', I tried this code:

val info = map.get(key) match {
  case Some(personInfo) => personInfo
  case None =>
    map.get(key.toUpperCase()) match {
      case Some(personInfo) => personInfo
      case None             => None
    }
}

but this return info as type of Product with Serializable, how can I have info returned as type of PersonInfo? Is there a way in Scala that allow me to get value from map by key and ignore cases of the key?


Solution

  • There are comparators for sorted maps which allow getting from the map case insensitively. Example: https://scastie.scala-lang.org/PfHTh16CROag7PNrknx1sQ

    val map = scala.collection.immutable.SortedMap("key1" -> 45, "Key2" -> 43, "KEY3" -> 42)(scala.math.Ordering.comparatorToOrdering(String.CASE_INSENSITIVE_ORDER))
    map.get("key1") // Some(45)
    map.get("key2") // Some(43)
    map.get("key3") // Some(42)
    map.get("key4") // None
    

    Your actual problem can be fixed if you return Options on all cases, for example:

          val info = map.get(key) match {
            case somePi@Some(personInfo) => somePi
            case None => map.get(key.toUpperCase()) match {
              case Some(personInfo) => Some(personInfo)
              case None => None
            }
          }
    

    Note the somePi@ => somePi parts for referring the expression or the Some(personInfo).

    Probably worth explaining why you got this error message. I assume personInfo is a case class which implements Product and Serializable, just like None. The common type for them is Product with Serializable.