4-х последовательная последовательность к карте карт - PullRequest
7 голосов
/ 15 февраля 2011

Мне нужен более краткий способ преобразовать последовательность кортежей в карту карт. В качестве подписи я получаю в случае Tuple4:

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

Следующий код показываетмой недавний некрасивый код, который я использовал (введите A до D произвольно):

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

Обратите внимание на использование head при val z.

Было бы неплохо иметь более сжатый способ только для Tuple4, но, кроме того, интересно, как обобщить это на TupleN (N> = 2).

Есть ли хороший подход у кого-товозражаете?

Спасибо!

Ответы [ 2 ]

8 голосов
/ 15 февраля 2011

Лучшее, что я могу придумать, это:

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

Обобщение для кортежей с более высокой арностью довольно простое ... просто добавьте дополнительные вложенные приложения mapValues ​​(_groupBy (_._ n). ..и соответствующим образом скорректировать окончательное сопоставление с образцом.

Полное обобщение этой функции как функции на кортежи произвольной арности возможно с использованием списков HLists, но это, скорее всего, будет гораздо более тяжелым решением, чем необходимо здесь. I 'Я оставлю эту линию атаки в качестве упражнения для спрашивающего (или других комментаторов; -).

1 голос
/ 15 февраля 2011

Я бы посоветовал применить к кортежам:

implicit def Tup3Cut[A,B,C](tup: (A,B,C)) = new {
  def decapitate = (tup._2,tup._3)
}
implicit def Tup4Cut[A,B,C,D](tup: (A,B,C,D)) = new {
  def decapitate = (tup._2,tup._3,tup._4)
}

val tupleSeq = Seq((1,1d,"a",true),(1,1d,"b",true),(1,1d,"c",false),(1,2d,"c",true))

tupleSeq.groupBy(_._1).mapValues(
  _.map(_.decapitate).groupBy(_._1).mapValues(_.map(_.decapitate).toMap)
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...