Scala代码 - 我无法理解

时间:2011-01-26 10:56:16

标签: scala

我从朋友处获得了部分代码,我正在尝试理解它并以其他方式编写代码。 “gotowe”是("2011-12-22",-600.00)元素的排序列表

   val wartosci = gotowe.foldLeft (List(initial_ballance)){
     case ((h::t), x) => (x._2 + h)::h::t
     case _ => Nil
  }.reverse 

这是相当不错的,但是如何使用foldLeft? (我已经把所有额外的必要线放了):

  val max = wartosci.max
val min = wartosci.min
val wychylenie = if(math.abs(min)>max){math.abs(min)}else{max}

  def scale(x: Double) =
     (x / wychylenie) * 500

  def point(x: Double) =
   {val z:Int =  (500 - x).toInt
z}   

 val (points, _) = wartosci.foldLeft(("", 1)){case ((a, i), h) => (a + " " + (i * 4) + "," + point(scale(h)), i + 1)}

当我打印点数时,我有一个值列表,并且不知道为什么不能像值对那样

2 个答案:

答案 0 :(得分:5)

这里有几个概念在起作用,我们将依次检查这些概念以确定正在发生的事情:

  • foldLeft
  • 模式匹配

让我们先来看看foldLeft的定义:

  

def foldLeft [B](z:B)(f:(B,A)⇒B):B

     

将二元运算符应用于起始值以及此列表的所有元素,从左到右。

     

返回在此列表的连续元素之间插入op的结果,从左到右,左边是起始值z:op(... op(z,x1),x2,...,xn)其中x1,...,xn是此列表的元素。

因此,在您的示例中,我们将获取Tuple2 [String,Float](或类似的东西)的列表并将其折叠到值z中,在本例中是一个包含一个元素的List {{1} }。

现在,在这种情况下,我们的initial_balance是大括号内的代码。它使用模式匹配来组合f对中的部分函数 - 在这种情况下,(b,a)是'累积结果',b是列表中的下一个项目。这是折叠的关键所在 - 它将列表折叠成一个值,使用特定的规则来管理如何一次添加每个元素。

什么是模式匹配/部分功能?模式匹配是一种非常强大的技术,用于从输入数据中调节和提取事物。我们给它一些东西 - 表达式的a部分 - 告诉它如何在case之后处理它。这样做的好处是=>表达式不仅匹配数字或特定字符串,就像java中的switch语句一样,但可以匹配,例如,某个长度的列表或电子邮件地址,或特定的元组。更重要的是,您可以使用它来自动获取匹配的某些部分 - 电子邮件地址的域名,列表的第三个元素等。

我们将看看第一种模式:

case

左侧(case ((h::t), x) => (x._2 + h)::h::t之前)用于匹配我们正在寻找的值并提取我们关心的特定部分。在这种情况下,我们正在寻找一个元组,其中第一个元素是由头部(=>)和尾部(h)组成的列表,第二个元素只是下一个元素列表。 t是一个提取器模式 - 它匹配对象::(h,t),它通过将h::t添加到现有List t来构造h

当我们匹配此内容时,我们会按照List右侧的说明将=>折叠为累计值。为此,我们采用日期/值元组的右侧(x),将其添加到列表中的最后一个值(头部),然后将其自身推送到列表的头部。您会注意到这与我们在模式匹配中使用的语法相同 - 使用._2将元素添加到::

在这种情况下,效果是创建正在进行的运行总计。

第二种情况并没有真正做太多 - 这是一个捕获所有情况,但由于这是在折叠中使用它永远不会被调用 - 我们总是会返回看起来像List的东西

最后,我们扭转了整个事情!因此,我们留下的是每笔交易后的余额清单,从最旧到最年轻。

答案 1 :(得分:1)

这很简单。这只是作业的问题。你有这个:

val (points, _) = wartosci.foldLeft(("", 1)){...}

{...}内的内容无关紧要。 foldLeft的第一个参数将确定其结果的类型。由于它是("", 1),它将返回(String, Int)元组。

现在,您将其分配给(points, _)。像这样的赋值也是模式匹配。就像你写的那样:

var tmp: (String, Int) = _
val tmp: (String, Int) = wartosci.foldLeft(("", 1)){...} match {
    case (x, y) => tmp = (x, y)
}
val points = tmp._1

因此,points只会被分配String