我正在研究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)))]
如何使它更简单和正确?
答案 0 :(得分:2)
如果要将A值与定义的所有对应B值组合在一起,则可以使用groupBy(_._1)
按元组的第一个元素分组,然后通过应用{{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)))
以允许使用不同的A值