Scala:map + filter而不是foldLeft

Tab*_*lut 0 functional-programming scala foldleft

是否可以通过Scala中的map和filter的某种组合替换foldLeft函数?例如,关于此任务.

输入是三元组列表(学生姓名,课程,年级):

val grades = List(("Hans", "db", 2.3), ("Maria", "prog1", 1.0), ("Maria", "prog2", 1.3), ("Maria", "prog3", 1.7), ("Hans", "prog2", 1.7), ("Josef", "prog1", 1.3), ("Maria", "mathe1", 1.3), ("Josef", "db", 3.3), ("Hans", "prog1", 2.0))
Run Code Online (Sandbox Code Playgroud)

然后,每个学生应该绘制他们的课程和成绩列表.使用foldLeft,就像这样:

grades.foldLeft(Map[String, List[(String, Double)]]())((acc, e) => acc + (e._1 -> (acc.getOrElse(e._1, List()) ::: List((e._2, e._3))))).toList
Run Code Online (Sandbox Code Playgroud)

输出:

List[(String, List[(String, Double)])] = List((Hans,List((db,2.3), (prog2,1.7), (prog1,2.0))), (Maria,List((prog1,1.0), (prog2,1.3), (prog3,1.7), (mathe1,1.3))), (Josef,List((prog1,1.3), (db,3.3))))
Run Code Online (Sandbox Code Playgroud)

如何仅使用map和filter函数实现相同的输出?到目前为止我有这个,但输出略有不同.

grades.map(x => (x._1, List())).distinct.flatMap(x => grades.map(z => if(!x._2.contains(z._2, z._3)) (x._1, x._2 ::: List((z._2, z._3)))))
Run Code Online (Sandbox Code Playgroud)

Tim*_*Tim 5

使用groupBy是解决此问题的好方法:

grades
  .groupBy(_._1)
  .mapValues(_.map(t => (t._2, t._3)))
Run Code Online (Sandbox Code Playgroud)

(感谢m4gic从评论中建议的原始版本的改进)