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))