Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 如何在';拉链';清单有用吗?_Scala_Scala Collections - Fatal编程技术网

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}