Есть ли лучший способ преобразовать Seq «вложенных» кортежей в иерархию карт? - PullRequest
2 голосов
/ 26 января 2020

Для ясности иерархия карты строится постепенно. Последний оператор scala содержит решение, которое было скопировано из другого вопроса переполнения стека, который я не могу найти.

Это повторяющееся приложение того же шаблона. Есть ли лучший способ кодировать этот тип повторяющегося шаблона?

case class X(a: String, b: String, c: String, d: String )

val x = Seq(X("a", "b", "c", "d"), X("a", "b", "p", "q") )

x.map{case X(a,b,c,d) => (a -> (b -> (c, d)))}.groupBy(_._1)

x.map{case X(a,b,c,d) => (a -> (b -> (c, d)))}.groupBy(_._1).map{case (k,v) => (k -> v.map(_._2))}

x.map{case X(a,b,c,d) => (a -> (b -> (c, d)))}.groupBy(_._1).map{case (k,v) => (k -> v.map(_._2).groupBy(_._1).map{case (k,v) => (k -> v.map(_._2))})}

x.map{case X(a,b,c,d) => (a -> (b -> (c, d)))}.groupBy(_._1).map{case (k,v) => (k -> v.map(_._2).groupBy(_._1).map{case (k,v) => (k -> v.map(_._2).groupBy(_._1).flatMap(_._2))})}

scala> case class X(a: String, b: String, c: String, d: String )
defined class X

scala>   val x = Seq(X("a", "b", "c", "d"), X("a", "b", "p", "q") )
x: Seq[X] = List(X(a,b,c,d), X(a,b,p,q))

scala>   x.map{case X(a,b,c,d) => (a -> (b -> (c, d)))}.groupBy(_._1)
res5: scala.collection.immutable.Map[String,Seq[(String, (String, (String, String)))]] = Map(a -> List((a,(b,(c,d))), (a,(b,(p,q)))))

scala>   x.map{case X(a,b,c,d) => (a -> (b -> (c, d)))}.groupBy(_._1).map{case (k,v) => (k -> v.map(_._2))}
res6: scala.collection.immutable.Map[String,Seq[(String, (String, String))]] = Map(a -> List((b,(c,d)), (b,(p,q))))

scala>   x.map{case X(a,b,c,d) => (a -> (b -> (c, d)))}.groupBy(_._1).map{case (k,v) => (k -> v.map(_._2).groupBy(_._1).map{case (k,v) => (k -> v.map(_._2))})}
res7: scala.collection.immutable.Map[String,scala.collection.immutable.Map[String,Seq[(String, String)]]] = Map(a -> Map(b -> List((c,d), (p,q))))

scala>   x.map{case X(a,b,c,d) => (a -> (b -> (c, d)))}.groupBy(_._1).map{case (k,v) => (k -> v.map(_._2).groupBy(_._1).map{case (k,v) => (k -> v.map(_._2).groupBy(_._1).flatMap(_._2))})}
res8: scala.collection.immutable.Map[String,scala.collection.immutable.Map[String,scala.collection.immutable.Map[String,String]]] = Map(a -> Map(b -> Map(p -> q, c -> d)))

Ответы [ 2 ]

1 голос
/ 26 января 2020

Я могу поспорить, что это немного яснее, немного лаконичнее и дает лучший результат.

x.groupBy(_.a)
 .map(kv0 => kv0._1 -> kv0._2.groupBy(_.b)
 .map(kv1 => kv1._1 -> kv1._2.groupMap(_.c)(_.d)))  //<--Note: Scala 2.13

Я полагаю, что это может быть лучшим результатом, потому что ваш тип результата:

Map[String,Map[String,Map[String,String]]]

Пока мой:

Map[String,Map[String,Map[String,Seq[String]]]]

Разница может быть продемонстрирована с помощью этого ввода.

val x = Seq( X("a", "b", "c", "d")    //c -> d
           , X("a", "b", "p", "q")    //p -> q
           , X("a", "b", "c", "q") )  //c -> q

Ваш результат: Map(a -> Map(b -> Map(p -> q, c -> q))) //lost c -> d

Мой результат: Map(a -> Map(b -> Map(p -> Seq(q), c -> Seq(d, q))))

0 голосов
/ 26 января 2020
  x.groupBy(_.a)
   .mapValues { _.groupBy(_.b)
     .mapValues(
      _.map { case X(_,_,c,d) => c -> d }.toMap
     )
   }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...