既然你已經編輯了一個幾乎完全不同的問題,我會給出一個不同的答案。而不是指向地圖和摺疊教程,我只會給一個。
在斯卡拉,你首先需要知道如何創建一個匿名函數。它是這樣的話,從最一般到更具體:
(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