Let's assume we have a list of objects
case class Cake(id: Int, name: String, expired: Long)
val l = List(Cake(1,"keks"), Cake(1,"keks"), Cake(1,"keks"), Cake(4,"pie"))
start to count
l.groupBy(_.id).map(pair => (pair._1, pair._2.length))
// res0: scala.collection.immutable.Map[Int,Int] = Map(4 -> 1, 1 -> 3)
good, but what if we wanna get all object as a key
l.groupBy(_.id)
.map({
case (_, items) => items.head -> items.length
})
// res1: scala.collection.immutable.Map[Cake,Int] = Map(Cake(4,pie) -> 1, Cake(1,keks) -> 3)
Match better. When pull request with this code come to review I get comment from my colleague
head
is not safety so it's bad
So, we need to change it
l.groupBy(_.id)
.map({
case (_, items) => items.headOption.map(_ -> items.length)
})
// res2: scala.collection.immutable.Iterable[Option[(Cake, Int)]] = List(Some((Cake(4,pie),1)), Some((Cake(1,keks),3)))
And then beautiful trick with List[Option[_]]
l.groupBy(_.id)
.map({
case (_, items) => items.headOption.map(_ -> items.length)
}).flatten
//res3: scala.collection.immutable.Iterable[(Cake, Int)] = List((Cake(4,pie),1), (Cake(1,keks),3))
finishing touch
l.groupBy(_.id)
.flatMap({
case (_, items) => items.headOption.map(_ -> items.length)
})
//res4: scala.collection.immutable.Iterable[(Cake, Int)] = List((Cake(4,pie),1), (Cake(1,keks),3))
Question: Do you agree with my colleague opinion?
Top comments (1)
I disagree. In this context, head is guaranteed to exist, as there would not be a pair generated from groupby that is (somekey, EmptyList), as somekey had to come from at least one item.