Scala 函数接受一张地图,修改值和 returns 一张地图

Scala function takes a map, modify the values and returns a map

我正在努力了解与 Maps 相关的 Scala for 理解。我有以下代码,我的目的是分解键值对,对值和 return 修改后的 Map 做一些事情。我使用的是正确的功能还是应该使用其他功能?

val kvpair = Map("a" -> 1, "b" -> 2, "c" -> 3)

def multiplyValues(map: Map[Char, Int]) = {

          for {
              char <- map._1  
              value <- map._2 * 2
          } yield (char, value )
  }

Map中,方法mapValues传达了这个要求;例如,

kvpair.mapValues(_ * 2)

将地图中的每个值加倍。

简单到:

def multiplyValues(map: Map[Char, Int]) =
  for {
    (char,value) <- map
    modValue = value * 2
  } yield (char, modValue)

def multiplyValues(map: Map[Char, Int]) =
  for ((char,value) <- map) yield (char, value* 2)

甚至

def multiplyValues(map: Map[Char, Int]) = map mapValues (_ * 2)

虽然还有其他(可能更优雅)方法可以做到这一点(请参阅@elm 的回答),但如果您想 use/learn 理解,这个方法非常好。

正如其他人在此处所述,您可能正在寻找的方法称为 mapValues:

val myMap = Map("one" -> 1, "two" -> 2)
val newMap = myMap.mapValues(_ + 1)  

println(newMap) //Map(one -> 2, two -> 3)

但是你必须非常小心地使用该方法,因为它的底层实现是一个视图,这意味着它是延迟计算的。由于 immutable.Map 上的大多数其他方法的行为都不相似,这可能会令人惊讶、困惑或导致错误。例如:

val it = Iterator.from(0)
val myMap = Map("one" -> 1, "two" -> 2)
val newMap = myMap.mapValues(_ + it.next)

println(newMap) //Map(one -> 3, two -> 5), as expected
//Try printing again, though:
println(newMap) //Map(one -> 5, two -> 7), I thought this map was immutable!

因此每次迭代地图时都会重新评估 newMap 中的值!这是通过延迟地图评估并尽可能避免迭代来实现的优化。这可能是违反直觉的,由于与这种混淆相关的问题,这种方法甚至有 several other questions and blog posts 专门用于它,如果您有兴趣使用这种方法,值得一读。

在使用简洁的 mapValues 语法的同时获得稳定映射的一种方法是 force 映射的底层 view 实现:

val newMap = myMap.mapValues(_ + it.next).view.force //now stable!

您也可以调用 toSeq,然后调用 toMap,但这会影响性能。

归根结底,使用常规 mapfor 理解可能会更简单:

//If you prefer "map":
myMap.map { case (key, value) => (key, value + 1) }
//If you prefer "for"
for { (key, value) <- map } yield (key, value + 1)