Scala 代码 —我不明白

发布于 2024-10-14 05:14:38 字数 732 浏览 1 评论 0原文

我从朋友那里得到了部分代码,我正在尝试理解它并以其他方式编写它。 “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)}

当我打印点时,我得到了一个值列表,并且不知道为什么不是类似值对的东西

I've got part of code from friend and I'm trying to understand it and write it in some other way. "gotowe" is a sorted list of ("2011-12-22",-600.00) elements

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

That is quite okay but how with this usage of foldLeft? (I've put all extra necessary lines):

  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)}

when I print points I've got a list of values, and don't know why not something like pairs of values

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

深海夜未眠 2024-10-21 05:14:38

这里有几个概念在起作用,我们将依次检查它们以弄清楚发生了什么:

  • 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 中,在本例中,该列表包含一个元素 initial_balance

现在,本例中的 f 是大括号内的代码。它使用模式匹配从 (b,a) 对组成部分函数 - 在本例中,b 是“累积结果”,a code> 是列表中的下一项。这是折叠功能的关键 - 它将列表折叠成一个值,使用特定的规则来管理如何一次添加每个元素。

什么是模式匹配/偏函数?模式匹配是一种非常强大的技术,用于调节输入数据并从输入数据中提取内容。我们给它一些东西来寻找 - 表达式的 case 部分 - 并告诉它如何在 => 之后处理它。其强大之处在于 case 表达式不仅可以像 Java 中的 switch 语句那样匹配数字或特定字符串,还可以匹配特定长度的列表,或者电子邮件地址或特定元组。更重要的是,您可以使用它自动获取匹配的某些部分 - 电子邮件地址的域、列表的第三个元素等。

我们将查看第一个模式:

case ((h::t ), x) => (x._2 + h)::h::t

左侧(=> 之前)用于匹配我们要查找的值并提取特定的值我们关心的部分。在本例中,我们正在寻找一个元组,其中第一个元素是由头 (h) 和尾 (t) 组成的列表,第二个元素是只是列表的下一个元素。 h::t 是一个提取器模式 - 它与对象 ::(h,t) 匹配,该对象通过在前面添加 h 来构造一个 List现有的List t。

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

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

第二种情况并没有真正做太多事情 - 这是一个包罗万象的情况,但由于这是在折叠中使用的,所以它永远不会被调用 - 我们总是会返回看起来像 ((h:: t),x)

最后,我们扭转了整个局面!因此,我们留下的是每笔交易后的余额列表,从最旧到最年轻。

There are a couple of concepts at work here, which we'll examine in turn to work out what's going on:

  • foldLeft
  • Pattern matching

Let's first look at the definition of foldLeft:

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

Applies a binary operator to a start value and all elements of this list, going left to right.

Returns the result of inserting op between consecutive elements of this list, going left to right with the start value z on the left: op(...op(z, x1), x2, ..., xn) where x1,..., xn are the elements of this list.

So, in your example we're taking a list of Tuple2[String, Float] (or something like that) and folding it into the value z, which in this case is a List containing one element, initial_balance.

Now, our f in this case is the code inside the braces. It uses pattern matching to compose a partial function from the pair (b,a) - where in this case b is the 'cumulative result' and a is the next item in the list. This is the crux of what a fold does - it collapses the list into a value, using specific rules governing how to add each element at a time.

What is pattern matching / a partial function? Pattern matching is a very powerful technique for conditioning on and extracting things from input data. We give it something to look for - the case part of the expression - and tell it how to deal with it following the =>. The power of this is that the case expression doesn't just match, say, numbers or specific strings as might the switch statement in java, but can match, for example, Lists of a certain length, or email addresses, or specific tuples. Even more, you can use it to automatically get certain parts of the match - the domain of the email address, the third element of the list etc.

We'll look at the first pattern:

case ((h::t), x) => (x._2 + h)::h::t

The left hand side (before the =>) is used to match the value we're looking for and extract the specific pieces we care about. In this case, we're looking for a tuple where the first element is a list consisting of a head (h) and a tail(t), and the second element is just the next element of the list. The h::t is an extractor pattern - it's matching the object ::(h,t) which constructs a List by prepending h onto an existing List t.

When we've matched this, we follow the instructions to the right of the => to fold x into the cumulative value. To do this, we take the right hand side of the date/value tuple (the ._2), add it to the last value in the list (the head), and then push itself on to the head of the list. You'll notice this is using the same syntax as we used in the pattern match - using :: to prepend elements to a List.

The effect in this case is to create a running total of what's going on.

The second case doesn't really do much - it's a catch all case, but as this is being used in a fold it should never get called - we're always going to return something that looks like ((h::t), x).

Finally, we reverse the whole thing! So what we're left with is a list of balances after each transaction, running from oldest to youngest.

花开雨落又逢春i 2024-10-21 05:14:38

这很简单。这只是任务的问题。你有这样的:

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

This is quite simple. It's just the matter of the assignment. You have this:

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

What is inside {...} is not relevant. The first parameter of foldLeft will determine the type of its result. Since it is ("", 1), it will return a (String, Int) tuple.

Now, you assign it to (points, _). An assignment like this is also a pattern match. It is like you had written this:

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

So, points only gets assigned the String.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文