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
占用的内存少,效率可能会更高,也可能不会更高,这取决于访问元素的频率感谢您的建议,但我举的例子是为了问一个更简单的问题,而不是一个更大的问题。