Convert list [Task (username, description)] to Map [username, Set [Task]]
(NOTE: I stop working with Scala and continue to struggle with the most common collection manipulation operations.)
I would like to convert a List [Task] to a Map. Here are some details:
// assignee may be null
case class Task(assignee: String, description: String)
// might refactor it into:
// case class Task(assignee: Option[String], description: String)
I want a Map where Keys are assignees and each value is a Set [Task]. I am having trouble managing the following two situations:
- The map is not (cough) friendly (cough) with null keys (I worked on this with the [String] option for assignee) and
- need to distinguish if the key exists in the map (just add the value to the existing set) and the key has already been added, so the Set value exists
I came up with the following, but it looks too verbose.
def groupByAssignee(tasks : List[Task]) : Map[Option[String], Set[Task]] = {
tasks.foldLeft(Map[Option[String], Set[Task]]())(
(m, t) => {
m.get(t.assignee) match {
case Some(_) => m + ((t.assignee, m.get(t.assignee).get.+(t)))
case _ => m + ((t.assignee, Set(t)))
}
})
}
What's an easier / cleaner way to achieve this?
Thank!
source to share
This use case is so common that there is a built-in method for it:
tasks groupBy {_.assignee}
groupBy
however will return Map[String,List[Task]]
as long as you want .Map[String, Set[String]]
. This should do it:
groupBy {_.assignee} mapValues {_ map {_.description} toSet}
groupBy
null
- friendly, but you don't have to be. Option[String]
much better and more idiomatic.
source to share