Brian Tarbox
Brian Tarbox

Reputation: 2375

How to use Scala reduceLeft on case classes?

I understand how to use reduceLeft on simple lists of integers but attempts to use if on case class objects fail.

Assume I have:

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

and I want to find the largest difference in time between LogMsgs. I want to do something like:

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

which of course doesn't work.
The first iteration of reduceLeft compares the first two elements, which are both of type LogMsg. After that it compares the next element (LogMsg) with the result of the first iteration (Int).

Do I just have the syntax wrong or should I be doing this another way?

Upvotes: 3

Views: 689

Answers (3)

Tomasz Nurkiewicz
Tomasz Nurkiewicz

Reputation: 340743

My try:

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

Another one that came into my mind: since LogMsg is a case class, we can take advantage of pattern matching:

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

Upvotes: 6

Christopher Chiche
Christopher Chiche

Reputation: 15335

I would recommand you to use foldLeft which is a reduceLeft enabling you to initialize the results.

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

Upvotes: 0

Luigi Plinge
Luigi Plinge

Reputation: 51109

I'd probably do something like this:

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

You'll need to check beforehand that cList has at least 2 elements.

reduceLeft can't be used to return the largest difference, because it always returns the type of the List you're reducing, i.e. LogMsg in this case, and you're asking for an Int.

Upvotes: 6

Related Questions