Если вы хотите собрать только «полные» значения
Я не уверен, почему вам нужен ящик [Список [T]], потому что пустого списка должно быть достаточно, чтобы сигнализировать об отсутствиилюбые значения.Я предполагаю, что это достаточно хорошо для вас.
У меня нет удобной копии Lift, но я знаю, что Box вдохновлен Option и имеет метод flatMap, поэтому:
Полная форма:
for {
box <- list
value <- box
} yield value
Более короткая форма:
list.flatMap(identity)
Кратчайшая форма:
list.flatten
Если вы также хотите собирать ошибки:
Вот функция mapSplit
, которую я использую для решения подобных задач.Вы можете легко адаптировать его для использования Box
вместо Either
:
/**
* Splits the input list into a list of B's and a list of C's, depending on which type of value the mapper function returns.
*/
def mapSplit[A,B,C](in: Traversable[A])(mapper: (A) ⇒ Either[B,C]): (Seq[B], Seq[C]) = {
@tailrec
def mapSplit0(in: Traversable[A], bs: Vector[B], cs: Vector[C]): (Seq[B], Seq[C]) = {
in match {
case t if t.nonEmpty ⇒
val a = t.head
val as = t.tail
mapper(a) match {
case Left(b) ⇒ mapSplit0(as, bs :+ b, cs )
case Right(c) ⇒ mapSplit0(as, bs, cs :+ c)
}
case t ⇒
(bs, cs)
}
}
mapSplit0(in, Vector[B](), Vector[C]())
}
И когда я просто хочу разделить что-то, что уже является Seq [Either [A, B]], я использую это:
/**
* Splits a List[Either[A,B]] into a List[A] from the lefts and a List[B] from the rights.
* A degenerate form of {@link #mapSplit}.
*/
def splitEither[A,B](in: Traversable[Either[A,B]]): (Seq[A], Seq[B]) = mapSplit(in)(identity)