2012-02-01 52 views
3

我明白如何在簡單的整數列表上使用reduceLeft,但是如果在case類對象失敗時嘗試使用reduceLeft。如何使用Scala reduceLeft對案例類?

假設我有:

case class LogMsg(time:Int, cat:String, msg:String) 
    val cList = List(LogMsg(1,"a", "bla"), LogMsg(2,"a", "bla"), LogMsg(4,"b", "bla")) 

,我想找到LogMsgs之間的時間差異最大。 我想要做的事,如:

cList.reduceLeft((a,b) => (b.time - a.time) 

這當然是行不通的。
reduceLeft的第一次迭代比較了前兩個元素,它們都是LogMsg類型。之後,它將下一個元素(LogMsg)與第一次迭代(Int)的結果進行比較。

我只是有語法錯誤或者我應該以另一種方式做這個?

+1

你 「 - 」應該返回一個LogMsg,而不是一個整數。覆蓋對象中的「 - 」運算符,而不是在時間對象上執行。 – 2012-02-01 17:04:33

回答

6

我可能會做這樣的事情:

(cList, cList.tail).zipped.map((a, b) => b.time - a.time).max 

你需要先確認是否cList至少有2個元素。

reduceLeft不能用於返回最大的區別,因爲它總是返回你該列表縮減,即LogMsg在這種情況下的類型,你問一個Int

0

我會建議您使用foldLeft這是一個reduceLeft使您能夠初始化結果。

val head::tail = cList 
tail.foldLeft((head.time, 0)) ((a,b) => (b.time, math.max(a._2,b.time-a._1)))._2 
+0

在這種情況下,這似乎給出了錯誤的答案......「3」,而正確的答案是「2」。 – 2012-02-01 18:34:31

+0

所以看來我不明白你想要什麼。根據我的研究,我會修改或刪除我的答案。 – 2012-02-01 21:43:24

+0

我的appologies,我看到我不清楚我的問題。我正在尋找列表中相鄰項目時間值的最大差異。由於列表中的時間值是1,2,4,所以最大差異將是4-2 = 2,而不是最大差異(4-1 = 3)。 – 2012-02-01 21:50:24

6

我嘗試:

cList.sliding(2).map(t => t(1).time - t(0).time).max 

是進入了我的腦海裏還有一句:既然LogMsg是一個案例類,我們可以利用模式匹配的優勢:

cList.sliding(2).collect{ 
    case List(LogMsg(a, _, _), LogMsg(b, _, _)) => b - a}. 
max 
+0

+1的滑動。 – Dylan 2012-02-01 20:46:59

+0

我喜歡這個,「滑動」看起來比「zipped.map」更直觀(這可能只是另一種說法,我沒有完全理解「zipped.map」!) – 2012-02-01 21:30:28

+0

@BrianTarbox如果我重寫了zipped.map這條路? '(cList,xcList.tail).zipped.map(t => t._2.time - t._1.time).max'。 'cList.sliding(2)'幾乎和'(cList,cList.tail).zipped'一樣,除了前者使用2元素的Vector,而後者使用2元組。 – 2012-02-02 01:35:05