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
,但这会影响性能。
归根结底,使用常规 map
或 for
理解可能会更简单:
//If you prefer "map":
myMap.map { case (key, value) => (key, value + 1) }
//If you prefer "for"
for { (key, value) <- map } yield (key, value + 1)
我正在努力了解与 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
,但这会影响性能。
归根结底,使用常规 map
或 for
理解可能会更简单:
//If you prefer "map":
myMap.map { case (key, value) => (key, value + 1) }
//If you prefer "for"
for { (key, value) <- map } yield (key, value + 1)