Вы можете просто выполнить итерацию по списку с помощью хвостовой рекурсивной функции, но это, вероятно, не очень кратко, но это может быть быстрее, чем второе решение, потому что оно повторяется только один раз по списку.
def flat[A,B](list: List[(A, List[B])]): Option[(NonEmptyList[A], NonEmptyList[B])] = {
@tailrec
def collapse(list: List[(A, List[B])], as: List[A], bs: List[B]): (List[A], List[B]) = {
list match {
case (a,b) :: xs => collapse(xs, a :: as, b ++ bs)
case Nil => (as, bs)
}
}
collapse(list, Nil, Nil) match {
case (a :: ax, b :: bx) => Some((NonEmptyList(a, ax), NonEmptyList(b, bx)))
case _ => None
}
}
Другой вариант - использовать unzip
:
def flat2[A,B](list: List[(A, List[B])]) = list.unzip match {
case (as,bs) => (as, bs.flatten) match {
case (a :: ax, b :: bx) => Some((NonEmptyList(a, ax), NonEmptyList(b, bx)))
case _ => None
}
}
Результат:
flat(List((1, List("a", "b")), (2, List("a", "c")), (3, List("d", "e")), (4, List("x", "y"))))
//Some((NonEmptyList(4, 3, 2, 1),NonEmptyList(x, y, d, e, a, c, a, b)))
flat(List((1, List()), (2, List("a"))))
//Some((NonEmptyList(2, 1),NonEmptyList(a)))
flat(List((1, List()), (2, List())))
//None
flat(List())
//None