2011-01-26 48 views
1

我已經有朋友的代碼的一部分,我試圖理解它,並以其他方式寫它。 「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)} 

當我打印點我有值的列表,不知道爲什麼不喜歡對值

+0

這似乎並不重要,但爲了完整:「wartości」的意思是「價值」,「gotowe」的意思是「準備好」。 – Bolo 2011-01-26 11:45:10

回答

5

有一個夫婦在這裏工作,我們將依次考察概念,就發生了什麼事情上:

  • foldLeft
  • 模式匹配

讓我們首先看看foldLeft的定義:

DEF foldLeft [B](Z:B)(F:(B,A)⇒B):乙

適用的二進制運算符給起始值和該列表的所有元素,從左到右。

返回在此列表的連續元素之間插入op的結果,從左到右,左起始值z:op(... op(z,x1),x2,...,xn)其中x1,...,xn是這個列表的元素。

所以,在你的榜樣,我們正在採取Tuple2 [字符串,浮點型(或類似的東西)的列表,並將其摺疊成z值,在這種情況下是包含一個元素的列表,initial_balance

現在,我們的f在這種情況下是括號內的代碼。它使用模式匹配來組合(b,a)中的部分函數 - 在這種情況下,b是「累計結果」,a是列表中的下一項。這是摺疊的關鍵 - 它將列表摺疊爲一個值,使用特定的規則來管理如何一次添加每個元素。

什麼是模式匹配/部分函數?模式匹配是一種非常強大的技術,用於調節和從輸入數據中提取事物。我們給它一些東西去尋找 - case表達的一部分 - 並告訴它如何處理=>之後。這樣做的威力在於,case表達式不僅可以與java中的switch語句匹配,比如數字或特定的字符串,而且可以匹配例如特定長度的列表或電子郵件地址或特定的元組。甚至,你可以用它來自動獲得比賽的某些部分 - 郵件地址的域名,列表的第三個元素等

我們將在第一模式:

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

左側(在=>之前)用於匹配我們正在查找的值並提取我們關心的特定部分。在這種情況下,我們正在尋找一個元組,其中第一個元素是一個包含頭部(h)和尾部(t)的列表,第二個元素只是列表中的下一個元素。 h::t是一個提取模式 - 它匹配的對象::(h,t)它構造了一個List通過預先h到現有的List噸。

當我們匹配這個時,我們按照=>右邊的說明將x折成累積值。爲此,我們採用日期/值元組的右側(._2),將它添加到列表中的最後一個值(頭部),然後將它自己推到列表的頭部。您會注意到它使用的語法與我們在模式匹配中使用的語法相同 - 使用::將元素前加到List

這種情況下的效果是創建正在發生的事件的總計。

第二種情況並沒有太大的作用 - 這是一種可以接受的情況,但是因爲它在摺疊中使用,它永遠不會被調用 - 我們總是會返回一些看起來像((h::t), x)的東西。

最後,我們扭轉了整個事情!所以我們剩下的是每次交易後的餘額清單,從最老的到最年輕的。

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