2012-02-01 73 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