Scala 在本例中,map和mapValues是如何工作的?

Scala 在本例中,map和mapValues是如何工作的?,scala,Scala,下面的代码将字符串转换为其二进制表示形式,以便 1 = 1,1,0,0 2 = 1,1,1,0 3 = 1,1,0,1 4 = 1,1,0,0 Returns 4-->1100 1-->1100 2-->1110 3-->1101 守则: import scala.collection.immutable.HashMap object BinaryRepFunctional extends Application { val userDetails = Ha

下面的代码将字符串转换为其二进制表示形式,以便

1 = 1,1,0,0
2 = 1,1,1,0
3 = 1,1,0,1
4 = 1,1,0,0

 Returns

4-->1100
1-->1100
2-->1110
3-->1101
守则:

import scala.collection.immutable.HashMap

object BinaryRepFunctional extends Application {
  val userDetails = HashMap("1" -> "ab",
                            "2" -> "abc",
                            "3" -> "abd",
                            "4" -> "ab")
  val lettersToCheck = "abcd"

  def getBinaryRepresentation = userDetails.mapValues(
      string => lettersToCheck.map(
          letter => if (string.contains(letter)) '1' else '0'))

  getBinaryRepresentation foreach ( (t2) => println (t2._1 + "-->" + t2._2))
}
这是mapValues的签名:

override def mapValues[C](f: B => C): Map[A, C] = 
  new MappedValues(f) with DefaultMap[A, C]
这是Map的签名,因此它接受一个函数paramater并应用它 函数调用集合中的每个项

  def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That = {
    def builder = { // extracted to keep method size under 35 bytes, so that it can be JIT-inlined
      val b = bf(repr)
      b.sizeHint(this)
      b
    }
    val b = builder
    for (x <- this) b += f(x)
    b.result
  }
defmap[B,That](f:A=>B)(隐式bf:CanBuildFrom[Repr,B,That]):That={
def builder={//提取以将方法大小保持在35字节以下,以便它可以JIT内联
val b=bf(报告)
b、 sizeHint(本)
B
}
val b=生成器

对于(x您的
userDetails
映射包含每个条目
1
2
,等等,结果的表示形式,但用字母替换位。例如,对于键
3
而言,值为
abd
,这意味着左侧的第一位、第二位和第四位(基于1位)应设置。函数
getBinaryRepresentation
遍历存储在
lettersToCheck
中的字母
abcd
,并根据该字母是否出现在相应条目中,将每个字母插入结果字符串
0
1

考虑到位字符串的长度最多为4位,直接将1和0的字符串存储在映射中并避免任何转换会简单得多。这样,代码就变得非常简单,如下所示:

object BinaryRepFunctional extends Application {
  val userDetails = HashMap("1" -> "1100",
                        "2" -> "1110",
                        "3" -> "1101",
                        "4" -> "1100")
  userDetails foreach ( (t2) => println (t2._1 + "-->" + t2._2))
}

如果您不理解当前形式的
getBinaryRepresentation
,这可能是因为您不熟悉函数式编程概念吗

map
方法通常采用从
a
B
的函数,并将其应用于
a
s集合的每个元素,以创建
B
s的集合。例如,给定定义为
x=>x+1
函数1[Int,Int]
(即增量运算符),这可以映射到集合
[1,7,42]
上,以给出[
2,8,43]

val lengthFn: Function1[String, Int] = { s => s.length }
val myColl = List("London", "Paris")
myColl map lengthFn   // returns List(6, 5)
这就是map所做的。
mapValues
非常相似-它只是一个专门的版本,作用于
map
并转换该地图中的每个值。因此,扩展上述示例:

val capitals = Map("England" -> "London", "France" -> "Paris")
capitals mapValues lengthFn    // returns Map("England" -> 6, "France" -> 5)

如果您理解这一点,那么
getBinaryRepresentation
的定义很简单。它采用
userDetails
映射,并对其每个值应用一个转换(因此结果将是一个具有相同键但不同值的映射)

应用于每个值
字符串的函数为

lettersToCheck.map(letter => if (string.contains(letter)) '1' else '0'))
这再次应用了映射,这次是在
字母上检查
列表(字符串
列表[Char]
)。每个字符依次根据函数进行转换:

if (string.contains(letter)) '1' else '0'
因此,列表中的每个字母都映射到
'1'
'0'
,这取决于
字符串是否包含它。这意味着应用于每个值的映射结果将是一个四个字符的字符串,根据每个键中包含的字母完全由1和0组成


所以整个过程的结果是一个映射,其中的值是从内部函数返回的四个字符的1和0字符串。当你仔细考虑它时,这很简单,但是我可以理解,如果你只是按照
Map
的实现中的代码行进行操作,而不理解它的意思是什么。

mapValues与map类似,但对于值:)map可以被视为成对(键,值)的列表。因此,当您只执行
map
-您转换一个元组
(键,值)
,但在
mapValues
中您只转换一个值。
mapValues(f)
相当于
map{case(k,v)=>k->f(v)}
。还要注意,
mapValues
是惰性的:生成的映射基本上是上一个映射的皮肤,在被访问时或被访问时将函数应用于现有值。因此,它比
map
占用的内存少,效率可能会更高,也可能不会更高,这取决于访问元素的频率感谢您的建议,但我举的例子是为了问一个更简单的问题,而不是一个更大的问题。