αƞjiβ
αƞjiβ

Reputation: 3246

Comparing two maps key with possibility of None and null in scala

I have this two Map[String, String] and I need to create new map with updated value. Update is done if second Map have new key or non-null value or value greater than of first Map.

For example:

Updating Scenario

Non-Updating Scenario

So far I have code below:

val currentFieldValue = currentDetail.get(field).get
val newFieldValue = newDetail.get(field).get

currentFieldValue match {
  case null if newFieldValue != null => currentDetail ++ Map(s"$field" -> s"$newFieldValue")
  case _ if newFieldValue != null && newFieldValue.toInt > currentFieldValue.toInt => currentDetail ++ Map(s"$field" -> s"$newFieldValue")
  case _  => currentDetail
}

Any suggestion on how to accommodate None state i.e. when key itself itsn't there?

Upvotes: 1

Views: 215

Answers (3)

jwvh
jwvh

Reputation: 51271

def combine(m1: Map[String,String], m2: Map[String,String]): Map[String,String] =
  (m1.keys ++ m2.keys).toSet.map{ k: String =>
    k -> Seq(Option(m1.getOrElse(k,"")), Option(m2.getOrElse(k,"")), Some(""))
         .flatten.sorted.reverse.head
  }.toMap

"456" > "123" is true for both String and Int. What if you have two strings "99" and "101"? If you need number comparisons then that's going to require lots more code to transit between String->Int->String.

Upvotes: 1

iuriisusuk
iuriisusuk

Reputation: 434

just as alternative here is complete compare function (with debug msgs):

def compare(currentDetail: Map[String, String], newDetail: Map[String, String]): Map[String, String] = {
  var resMap = Map[String, String]()
  currentDetail.keys.foreach { field =>

    val currentField = currentDetail.get(field)
    val newField = newDetail.get(field)

    resMap = resMap + {
      (currentField, newField) match {
        case (Some(null), Some(newFieldValue: String)) =>
          println("null and not null")
          (s"${field}" -> newFieldValue)
        case (Some(currentFieldValue), Some(null)) =>
          println("not null and null")
          (s"${field}" -> currentFieldValue)
        case (None, Some(newFieldValue)) =>
          println("none and not null")
          (s"${field}" -> newFieldValue)
        case (Some(currentFieldValue), None) =>
          println("not null and none")
          (s"${field}" -> currentFieldValue)
        case (Some(currentFieldValue), Some(newFieldValue)) if newFieldValue.toInt > currentFieldValue.toInt =>
          println("not null not null if new bigger then current")
          (s"${field}" -> newFieldValue)
        case (Some(currentFieldValue), Some(newFieldValue)) if newFieldValue.toInt <= currentFieldValue.toInt =>
          println("not null not null if new less or equal to current")
          (s"${field}" -> currentFieldValue)
      }
    }
  }

  resMap
}

Upvotes: 1

Nagarjuna Pamu
Nagarjuna Pamu

Reputation: 14825

map.get(key) returns Option pattern match on the option and create as many relevant cases as you want

(currentDetail.get(field), newDetail.get(field)) match {
  case (Some(null), Some(null)) =>
  case (Some(null), Some(value)) =>
  case (Some(value), Some(null)) => 
  case (Some(value), None) =>
  case (None, Some(value)) =>
  case (None, None) =>
  case (_, _) =>
}

Upvotes: 1

Related Questions