Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert a List[Task(username, description)] into Map[username,Set[Task]]

(NOTE I'm quit new to Scala and still struggle with most common operations of collection manipulation.)

I would like to convert a List[Task] into a Map. Here's 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 the assignees and each Value is a Set[Task]. I'm having trouble managing the following two situations:

  • Map's not being (cough) friendly (cough) with null Keys (I worked around this one using Option[String] for assignee) and
  • having to distinguish whether a Key already exists in the map (only add value to existing set) vs key already added so the Set value exists

I came up with the following but it looks overly 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 a easier/clearer way to achieve this?

Thanks!

like image 362
ignasi35 Avatar asked Dec 13 '25 20:12

ignasi35


1 Answers

This use case is so common that there is a built-in method for that:

tasks groupBy {_.assignee}

groupBy however will return Map[String,List[Task]] while you want .Map[String, Set[String]]. This should do it:

groupBy {_.assignee} mapValues {_ map {_.description} toSet}

groupBY is null-friendly, but you shouldn't be. Option[String] is much better and more idiomatic.

like image 84
Tomasz Nurkiewicz Avatar answered Dec 16 '25 15:12

Tomasz Nurkiewicz