Есть ли более идиоматический способ упростить результаты левого соединения? - PullRequest
0 голосов
/ 03 июня 2019

Я работаю над проектами Scala 2.12.x и Slick 3.3.0, и у меня есть периодический случай использования результатов операции joinLeft.

Левое объединение дает мне такой результат: Future[Seq[(A, Option[B])]], где A - это тип мастер-таблицы, а B - это тип подробных таблиц. Другими словами, я получаю последовательность мастер-элемента A, повторяемую столько раз, сколько оставшихся объединенных экземпляров B. Я хотел бы упростить этот сложный повторяющийся тип до более управляемого типа результата Future[Option[(A, Seq[B])]]. Для этого я создал следующую функцию:

implicit def simplify[A, B](x: Future[Seq[(A, Option[B])]])(implicit ec: ExecutionContext): Future[Option[(A, Seq[B])]] = {
  x.map {
    case results => {
      val seq: Seq[B] = results.map(_._2).map {
        case Some(b) => Some(b)
        case _ => None.asInstanceOf[Option[B]]
      }.filterNot(_.isEmpty).map(_.get) match {
        case seq if (seq.nonEmpty) => seq
        case _ => Seq()
      }

      results.headOption.map {
        case (a, _) => (a, seq)
      }
    }
  }
}

, но выглядит он слишком сложным И не учитывает тот факт, что может быть более одного A экземпляра, например,

a1 b11
a1 b12
a1 b13
a2 b21
a2 b22

Обратите внимание, что в этом случае моя функция выдаст неверный результат: Future[Some((a1, Seq(b11, b12, b13, b21, b22)))], правильный результат будет Future[Some((a1, Seq(b11, b12, b13)))]

Как мне сделать это проще и правильнее?

1 Ответ

2 голосов
/ 04 июня 2019

Если вы хотите объединить значения A со всеми соответствующими соответствующими значениями B, вы можете использовать groupBy(_._1) для группировки по первому элементу кортежа, а затем сгладить параметры B, применив mapValues(_.flatMap(_._2))

def simplify[A, B](x: Future[Seq[(A, Option[B])]])(implicit ec: ExecutionContext)
   : Future[Map[A, Seq[B]]] =
  x.map(_.groupBy(_._1).mapValues(_.flatMap(_._2)))

Я изменил тип возвращаемого значения на Future[Map[A, Seq[B]]], чтобы разрешить разные значения A

...