0

Is it possible to substitute the foldLeft function through some combination of map and filter in Scala? For example on this task.

Input is a list of triples (student name, course, grade):

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

Then to each student, a list of their courses and grades should be mapped. With foldLeft it goes like that:

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

Output:

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

How to achieve the same output using only map and filter functions? So far i have this, but the output is slightly different.

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)))))
Frumda Grayforce
  • 119
  • 1
  • 13
  • Using a case class instead of a tuple/tripple will make the code easier to read and reduce bugs – Simon Sep 05 '18 at 07:59
  • This appears to be a programming challenge rather than a genuine request for help. Please restrict questions to genuine problems that you need solving. Thanks. – Tim Sep 06 '18 at 07:34

2 Answers2

5

Using groupBy is a nice way to tackle this problem:

grades
  .groupBy(_._1)
  .mapValues(_.map(t => (t._2, t._3)))

(Thanks to m4gic from improvement to original version suggested in comment)

Tim
  • 26,753
  • 2
  • 16
  • 29
0
grades
  .map({ case (name, _, _) => name })
  .distinct
  .map(name => {
    val scores = grades
      .filter({ case (nameInternal, _, _) => name == nameInternal })
      .map({ case (_, subject, score) => (subject, score) })
    (name, scores)
  })

// res0: 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))))
sarveshseri
  • 13,738
  • 28
  • 47