既然你已经编辑了一个几乎完全不同的问题,我会给出一个不同的答案。而不是指向地图和折叠教程,我只会给一个。
在斯卡拉,你首先需要知道如何创建一个匿名函数。它是这样的话,从最一般到更具体:
(var1: Type1, var2: Type2, ..., varN: TypeN) => /* output */
(var1, var2, ..., varN) => /* output, if types can be inferred */
var1 => /* output, if type can be inferred and N=1 */
下面是一些例子:
(x: Double, y: Double, z: Double) => Math.sqrt(x*x + y*y + z*z)
val f:(Double,Double)=>Double = (x,y) => x*y + Math.exp(-x*y)
val neg:Double=>Double = x => -x
现在,列出的map
方法和这样就会将一个函数(匿名或其他方式)地图的每个元素。也就是说,如果你有
List(a1,a2,...,aN)
f:A => B
然后
List(a1,a2,...,aN) map (f)
产生
List(f(a1) , f(a2) , ..., f(aN))
有很多原因,这可能是有用的种种。也许你有一串字符串,你想知道每个字符串的长度,或者你想让它们全部大写,或者你想让它们向后。如果你有一个函数,它要一个元素,地图将它做的所有元素的内容:
scala> List("How","long","are","we?") map (s => s.length)
res0: List[Int] = List(3, 4, 3, 3)
scala> List("How","capitalized","are","we?") map (s => s.toUpperCase)
res1: List[java.lang.String] = List(HOW, CAPITALIZED, ARE, WE?)
scala> List("How","backwards","are","we?") map (s => s.reverse)
res2: List[scala.runtime.RichString] = List(woH, sdrawkcab, era, ?ew)
所以,这就是地图一般,并在斯卡拉。
但是如果我们想收集我们的结果呢?这就是折叠进来的地方(foldLeft
是从左边开始并且正确的版本)。
假设我们有一个功能f:(B,A) => B
,也就是说,它需要一个B和一个A,并将它们组合起来产生B.嗯,我们可以用B开始,然后在养活我们A的名单其中的一个一段时间,最后,我们会有一些B.这正是折叠所做的。 foldLeft
是从列表的左端开始的; foldRight
从右侧开始。也就是说,
List(a1,a2,...,aN) foldLeft(b0)(f)
产生
f(f(... f(f(b0,a1) , a2) ...), aN)
其中b0
是的,当然,你的初始值。
因此,也许我们有一个函数,它接受一个int和一个字符串,并返回int或字符串的长度,以较大者为准 - 如果我们使用它来折叠列表,它会告诉我们最长的字符串(假设我们从0开始)。或者我们可以将长度添加到int中,随着我们的进行累积值。
让我们试试吧。
scala> List("How","long","is","longest?").foldLeft(0)((i,s) => i max s.length)
res3: Int = 8
scala> List("How","long","is","everyone?").foldLeft(0)((i,s) => i + s.length)
res4: Int = 18
好,好,但如果我们想知道什么是谁的时间最长?一种方式(可能不是最好的,但它很好地说明了一种有用的模式)是携带领先竞争者(字符串)的长度(整数)和。让我们给一个去:
scala> List("Who","is","longest?").foldLeft((0,""))((i,s) =>
| if (i._1 < s.length) (s.length,s)
| else i
|)
res5: (Int, java.lang.String) = (8,longest?)
这里,i
现在是(Int,String)
类型的元组,而i._1
是元组(一个Int)的第一部分。
但在某些情况下,使用折叠并不是我们想要的。如果我们想要两个字符串中较长的一个,最自然的功能应该是max:(String,String)=>String
。我们如何应用那一个?
那么,在这种情况下,有一个默认的“最短”的情况,所以我们可以折叠以“”开头的string-max函数。但更好的方法是使用减少。与折叠一样,有两个版本,一个从左侧开始工作,另一个从右侧开始工作。它不需要初始值,并且需要功能f:(A,A)=>A
。也就是说,它需要两件事,并返回一个相同的类型。下面是一个带字符串最大值函数的例子:
scala> List("Who","is","longest?").reduceLeft((s1,s2) =>
| if (s2.length > s1.length) s2
| else s1
|)
res6: java.lang.String = longest?
现在,只有两个技巧。首先,以下两个意思是相同的:
list.foldLeft(b0)(f)
(b0 /: list)(f)
通知二是如何更短,这有点给你,你正在做b0
,并做一些列表它(你的印象)。 (:\
是一样的foldRight
,但你使用它,像这样:(list :\ b0) (f)
其次,如果你只引用变量一次,就可以使用_
而不是变量名称并省略匿名函数声明x =>
部分这里有两个例子:
scala> List("How","long","are","we?") map (_.length)
res7: List[Int] = List(3, 4, 3, 3)
scala> (0 /: List("How","long","are","we","all?"))(_ + _.length)
res8: Int = 16
在这一点上,你应该能够创建功能和地图,折叠,并使用Scala的降低。因此,如果你知道你的算法应该是如何工作的,应该是合理的直接执行它。
你在s艾米级汤姆?请参阅http://stackoverflow.com/questions/2274852/scala-how-to-perform-pattern-matching-with-vararg-case-classes。 – huynhjl 2010-02-19 03:45:22
这不是关于Scala和'foldLeft'的问题。这是一个关于算法的问题。你最好问 - “如何使用不可变数据结构计算形状列表中的最小边界框?”。将问题标记为与语言无关的算法和算法。也许功能编程。如果您在实现Scala中建议的算法时遇到问题,那么您可以打开一个关于它的Scala问题。目前的问题是针对错误的群体。 – 2010-02-19 12:11:28