Search code examples
scalapointfree

Transform a list of tuple sequences in Scala


Let's say I have 3 tuple sequences that look something like this:

Seq("m1" -> 1, "m2" -> 2)
Seq("m3" -> 3, "m4" -> 4)
Seq("m5" -> 5, "m2" -> 6)

I would like to map over these and return 3 new records that look something like the following:

Seq("m1" -> Some(1), "m2" -> Some(2), "m3" -> None, "m4" -> None, "m5" -> None)
Seq("m1" -> None, "m2" -> None, "m3" -> Some(3), "m4" -> Some(4), "m5" -> None)
Seq("m1" -> None, "m2" -> Some(6), "m3" -> None, "m4" -> None, "m5" -> Some(5))

The new collection that I'm looking for contains a key for the distinct set of keys from the original list and values of Some(v) or None based on whether or not the corresponding original sequence contained the tuple.

I managed to pull out the keys from the original list:

case class SiteReading(val site: String, val measures: Seq[(String, Double)])
val xs = getSomeSiteReadingsFromSomewhere()
val keys = xs.flatMap(_.measures.map(t => t._1)).distinct

I now plan to go through the whole list again, generating a new list by looking at both the current value and the unique set of keys. I'm wondering if there are some nifty things in the collections framework that makes this a little cleaner and more tractable? Maybe point-free?


Solution

  • val s1 = Seq("m1" -> 1, "m2" -> 2)
    val s2 = Seq("m3" -> 3, "m4" -> 4)
    val s3 = Seq("m5" -> 5, "m2" -> 6)
    val ss = Seq(s1, s2, s3)
    def foo(xss: Seq[Seq[(String,Int)]]): Seq[Seq[(String,Option[Int])]] = {
      val keys = xss.flatMap(_.map(_._1)).toSet
      xss.map{ xs => 
        val found = xs.map{ case (s,i) => (s, Some(i)) }
        val missing = (keys diff xs.map(_._1).toSet).map(x => (x, None)).toSeq
        (found ++ missing).sortBy(_._1)
      }
    }
    
    scala> foo(ss).foreach(println)
    List((m1,Some(1)), (m2,Some(2)), (m3,None), (m4,None), (m5,None))
    List((m1,None), (m2,None), (m3,Some(3)), (m4,Some(4)), (m5,None))
    List((m1,None), (m2,Some(6)), (m3,None), (m4,None), (m5,Some(5)))