Idiomatic way to update value in a Map based on previous value

后端 未结 4 729
日久生厌
日久生厌 2020-12-08 00:35

Let\'s say I store bank accounts information in an immutable Map:

val m = Map(\"Mark\" -> 100, \"Jonathan\" -> 350, \"Bob\" -> 65)
         


        
4条回答
  •  一生所求
    2020-12-08 00:53

    Starting Scala 2.13, Map#updatedWith serves this exact purpose:

    // val map = Map("Mark" -> 100, "Jonathan" -> 350, "Bob" -> 65)
    map.updatedWith("Mark") {
      case Some(money) => Some(money - 50)
      case None        => None
    }
    // Map("Mark" -> 50, "Jonathan" -> 350, "Bob" -> 65)
    

    or in a more compact form:

    map.updatedWith("Mark")(_.map(_ - 50))
    

    Note that (quoting the doc) if the remapping function returns Some(v), the mapping is updated with the new value v. If the remapping function returns None, the mapping is removed (or remains absent if initially absent).

    def updatedWith[V1 >: V](key: K)(remappingFunction: (Option[V]) => Option[V1]): Map[K, V1]

    This way, we can elegantly handle cases where the key for which to update the value doesn't exist:

    Map("Jonathan" -> 350, "Bob" -> 65)
      .updatedWith("Mark")({ case None => Some(0) case Some(v) => Some(v - 50) })
    // Map("Jonathan" -> 350, "Bob" -> 65, "Mark" -> 0)
    Map("Mark" -> 100, "Jonathan" -> 350, "Bob" -> 65)
      .updatedWith("Mark")({ case None => Some(0) case Some(v) => Some(v - 50) })
    // Map("Mark" -> 50, "Jonathan" -> 350, "Bob" -> 65)
    
    Map("Jonathan" -> 350, "Bob" -> 65)
      .updatedWith("Mark")({ case None => None case Some(v) => Some(v - 50) })
    // Map("Jonathan" -> 350, "Bob" -> 65)
    

提交回复
热议问题