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)}
当我打印点时,我得到了一个值列表,并且不知道为什么不是类似值对的东西
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这里有几个概念在起作用,我们将依次检查它们以弄清楚发生了什么:
让我们首先看一下foldLeft 的定义:
因此,在您的示例中,我们采用 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:
Let's first look at the definition of foldLeft:
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 caseb
is the 'cumulative result' anda
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 thecase
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. Theh::t
is an extractor pattern - it's matching the object ::(h,t) which constructs aList
by prependingh
onto an existingList
t.When we've matched this, we follow the instructions to the right of the
=>
to foldx
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 aList
.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.
这很简单。这只是任务的问题。你有这样的:
{...}
里面的内容是不相关的。foldLeft
的第一个参数将确定其结果的类型。由于它是("", 1)
,因此它将返回一个(String, Int)
元组。现在,您将其分配给
(points, _)
。像这样的赋值也是一种模式匹配。就像您写的那样:因此,
points
只会被分配String
。This is quite simple. It's just the matter of the assignment. You have this:
What is inside
{...}
is not relevant. The first parameter offoldLeft
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:So,
points
only gets assigned theString
.