【问题标题】:Convert a List[Task(username, description)] into Map[username,Set[Task]]将 List[Task(username, description)] 转换为 Map[username,Set[Task]]
【发布时间】:2013-01-20 11:54:38
【问题描述】:

注意我是 Scala 的新手,仍然在为最常见的集合操作操作而苦恼。)

我想将 List[Task] 转换为 Map。以下是一些细节:

// assignee may be null
case class Task(assignee: String, description: String)
// might refactor it into:
// case class Task(assignee: Option[String], description: String)

我想要一个地图,其中 Keys 是受让人,每个 Value 都是一个 Set[Task]。我无法处理以下两种情况:

  • 使用 null 键(我使用 Option[String] 作为受让人解决了这个问题)和
  • 必须区分映射中是否已存在键(仅向现有集合添加值)与已添加键因此集合值存在

我想出了以下内容,但它看起来过于冗长。

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

有什么更简单/更清晰的方法来实现这一点?

谢谢!

【问题讨论】:

    标签: scala collections grouping


    【解决方案1】:

    这个用例非常常见,因此有一个内置方法:

    tasks groupBy {_.assignee}
    

    groupBy 但是会在您想要.Map[String, Set[String]] 时返回Map[String,List[Task]]。应该这样做:

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

    groupBYnull 友好,但你不应该这样做。 Option[String] 更好,更惯用。

    【讨论】:

    • 这比我想出的要简单得多。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-09
    • 1970-01-01
    • 1970-01-01
    • 2016-10-15
    • 2015-09-19
    相关资源
    最近更新 更多