How to use MaxBy in Scala

I have a list that I would like to group into group and then for each group get the max value. For example, a list of actions of user, get the last action per user.

case class UserActions(userId: String, actionId: String, actionTime: java.sql.Timestamp) extends Ordered[UserActions] { def compare(that: UserActions) = this.actionTime.before(that.actionTime).compareTo(true)
}
val actions = List(UserActions("1","1",new java.sql.Timestamp(0L)),UserActions("1","1",new java.sql.Timestamp(1L)))

When I try the following groupBy:

actions.groupBy(_.userId)

I receive a Map

scala.collection.immutable.Map[String,List[UserActions]] = Map(1 -> List(UserActions(1,1,1970-01-01 00:00:00.0), UserActions(1,1,1970-01-01 00:00:00.001))

Which is fine, but when I try to add the maxBy I get an error:

actions.groupBy(_.userId).maxBy(_._2)
<console>:13: error: diverging implicit expansion for type
Ordering[List[UserActions]]
starting with method $conforms in object Predef actions.groupBy(_.userId).maxBy(_._2)

What should I change?

Thanks Nir

3 Answers

So you have a Map of String (userId) -> List[UserActions] and you want each list reduced to just its max element?

actions.groupBy(_.userId).mapValues(_.max)
//res0: Map[String,UserActions] = Map(1 -> UserActions(1,1,1969-12-31 16:00:00.0))

You don't need maxBy() because you've already added the information needed to order/compare different UserActions elements.

Likewise if you just want the max from the original list.

actions.max

You'd use maxBy() if you wanted the maximum as measured by some other parameter.

actions.maxBy(_.actionId.length)

Your compare method should be:

def compare(that: UserActions) = this.actionTime.compareTo(that.actionTime)

Then do actions.groupBy(_.userId).mapValues(_.max) as @jwvh shows.

You want to group values by using userId. You can do it by using groupBy().

actions.groupBy(_.userId)

Then you can take only values from key value pairs.

actions.groupBy(_.userId).values

You have used maxBy(_._2). So, I think You want to get max by comparing second value. You can do it by using map().

actions.groupBy(_.userId).values.map(_.maxBy(_._2))

2

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

You Might Also Like