Scala 如何在';拉链';清单有用吗?
我想计算两个列表的标量积。假设我们有两个列表,Scala 如何在';拉链';清单有用吗?,scala,scala-collections,Scala,Scala Collections,我想计算两个列表的标量积。假设我们有两个列表,l1=List(1,2,3)和l2=List(4,5,6),结果应该是List(4,10,18) 以下代码有效: def scalarProduct(l1 : List[Int], l2 : List[Int]):List[Int] = { val l3 = l1 zip(l2); l3 map(xy => xy._1*xy._2) } 但是,以下代码未能编译,并表示无法解析带有此类签名的参考地图: def scalarProduct(l
l1=List(1,2,3)
和l2=List(4,5,6)
,结果应该是List(4,10,18)
以下代码有效:
def scalarProduct(l1 : List[Int], l2 : List[Int]):List[Int] = {
val l3 = l1 zip(l2); l3 map(xy => xy._1*xy._2)
}
但是,以下代码未能编译,并表示无法解析带有此类签名的参考地图
:
def scalarProduct(l1 : List[Int], l2 : List[Int]):List[Int] = {
val l3 = l1 zip(l2); l3 map((x:Int,y:Int) => x*y)
}
这个zip()将返回一个Int对列表,上面的映射还使用了一个函数,该函数使用Int对。
有人能指出第二种变体在这种情况下失败的原因吗?您需要类似于:
def scalarProduct(l1 : List[Int], l2 : List[Int]):List[Int] = {
val l3 = l1 zip(l2); l3 map{ case (x:Int,y:Int) => x*y}
}
您可以查看以帮助您解决此类问题。您的第二个示例失败,因为您为
映射提供了一个带有2个参数的函数,而映射采用了一个带有1个参数的函数
看一看,这是map
函数的(简化)签名:
def map[B, That](f: A => B): That
{
case (x, y) => x * y
}
函数f
是进行转换时必须传递的函数。如您所见,它的类型为A=>B
,即接受单个参数
现在看一下(简化的)zip函数签名:
def zip [B](that : List[B]) : List[(A, B)]
它实际上生成一个成员为元组的列表。由2个元素组成的元组如下所示:(A,B)
。当您在元组列表上调用map
时,必须提供函数f
,该函数将2个元素的元组作为参数,就像您在第一个示例中所做的那样
因为直接使用元组不方便,所以可以使用模式匹配将元组成员的值提取到单独的变量中
下面是一个REPL会话来说明这一点
scala> List(1, 2, 3)
res0: List[Int] = List(1, 2, 3)
scala> List(2, 3, 4)
res1: List[Int] = List(2, 3, 4)
scala> res0 zip res1
res2: List[(Int, Int)] = List((1,2), (2,3), (3,4))
以下是如何使用模式匹配进行标准元组值提取:
scala> res2.map(t => t match {
| case (x, y) => x * y
| })
res3: List[Int] = List(2, 6, 12)
这里需要注意的是,模式匹配需要一个分部函数作为参数。即,以下表达式实际上是一个部分函数:
def map[B, That](f: A => B): That
{
case (x, y) => x * y
}
分部函数在Scala中有自己的类型:trait PartialFunction[-A,+B]扩展(A)=>B
,例如,您可以阅读更多关于它的内容
分部函数是一个普通函数,因为它扩展了(a)=>B
,这就是为什么可以将分部函数传递给map
调用:
scala> res2.map { case (x, y) => x * y }
res4: List[Int] = List(2, 6, 12)
实际上,您在这里使用了特殊的Scala语法,它允许函数调用(在本例中是映射),而不需要在其参数周围加括号。您也可以用括号将其写入,如下所示:
scala> res2.map ({ case (x, y) => x * y })
res5: List[Int] = List(2, 6, 12)
最后两次通话没有任何区别
在对其进行模式匹配之前,不必声明传递给map
的匿名函数的参数,这实际上是Scala的语法优势。当您调用res2.map{case(x,y)=>x*y}
时,实际发生的是使用部分函数进行模式匹配
希望这能有所帮助。当您使用带有列表的映射时,列表中的每个对象都有一个引用。因此,您需要模式匹配来将该引用转换为您可能使用的对象。对于这些情况,你不应该使用map(x=>x.\u1*x.\u2)
你应该使用map{x=>x match{case(x:Int,y:Int)=>x*y}
因为这很难看,我们可以使用一些语法糖:map{case(x:Int,y:Int)=>x*y}
这很奇怪,因为其中一个定义有map(f)
另一个定义有map{f}
。我不想承认,但我完全搞不清楚nowmap()是一个接受函数的方法。在回答中,我无法理解我们是将函数作为参数传递给map(),还是重新定义map()方法本身当我们使用括号时是因为我们在定义一个表达式。当我们使用大括号时,我们定义了一块代码。关于你的最后一条评论,我们将传递一个函数到map。事实上,我们正在定义这个函数。这太棒了!仅此一个答案就帮我解决了很多问题。谢谢..!如果你使用curl在地图上用大括号括起来,你不需要t=>t.match{
部分,只要做res2.map{case(x,y)=>x*y}