Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

4-Tuple Sequence To Map of Maps of Maps

Tags:

scala

I need a more concise way to transform a sequence of tuples into a map of maps of maps... As a signature I get in case of Tuple4:

def tuple4Seq2MapOfMaps[A,B,C,D](seq: Seq[(A,B,C,D)]): Map[A,Map[B,Map[C,D]]]

The following code shows my recent ugly code, I stucked with (type A to D arbitrary):

type A = Int
type B = Double
type C = String
type D = Boolean
val tupleSeq = Seq[(A,B,C,D)](
  (1,1.0D,"a",true),
  (1,1.0D,"b",true),
  (1,1.0D,"c",false)
)
val x = tupleSeq.groupBy{ _._1 }.map{ case (k,s) => (k,s.map{ x => (x._2,x._3,x._4) }) }
val y = x.map{ case (k,s) => (k,s.groupBy{_._1}.map{ case (k,s) => (k,s.map{ x => (x._2,x._3) }) }) }
val z = y.map{ case (k1,m) => (k1,m.map{ case (k2,s1) => (k2,s1.groupBy{_._1}.map{ case (k3,s2) => (k3,s2.map{ _._2 }.head) }) }) }

val m = z(1)(1.0D)
println(m("b"))

Note the use of head at val z.

It would be nice to have a more concise way for only Tuple4, but furthermore interesting how to generalize this to TupleN (N >= 2).

Is there a nice approach in someones mind out there?

Thank you!

like image 327
Peter Schmitz Avatar asked Feb 15 '11 16:02

Peter Schmitz


1 Answers

The best I can come up with is,

tupleSeq.groupBy(_._1).
  mapValues(_.groupBy(_._2).
    mapValues(_.groupBy(_._3).
      mapValues{ case Seq(p) => p._4 }))

Generalizing to tuples of higher arity is quite straightfoward ... just add additional nested applications of mapValues(_groupBy(_._n). ... and adjust the final pattern match accordingly.

Fully generalizing this as a function over tuples of arbitrary arity would be possible using HLists, but that would most likely be a far more heavyweight solution than is needed here. I'll leave this line of attack as an exercise for the questioner (or other commenters ;-).

like image 121
Miles Sabin Avatar answered Sep 29 '22 16:09

Miles Sabin