Просто хотел бы расширить ответ mkneissl с помощью «более общей» версии, которая должна работать со многими различными коллекциями в библиотеке:
scala> import collection._
import collection._
scala> import generic.CanBuildFrom
import generic.CanBuildFrom
scala> def partition[X,A,B,CC[X] <: Traversable[X], To, To2](xs : CC[X])(f : X => Either[A,B])(
| implicit cbf1 : CanBuildFrom[CC[X],A,To], cbf2 : CanBuildFrom[CC[X],B,To2]) : (To, To2) = {
| val left = cbf1()
| val right = cbf2()
| xs.foreach(f(_).fold(left +=, right +=))
| (left.result(), right.result())
| }
partition: [X,A,B,CC[X] <: Traversable[X],To,To2](xs: CC[X])(f: (X) => Either[A,B])(implicit cbf1: scala.collection.generic.CanBuildFrom[CC[X],A,To],implicit cbf2: scala.collection.generic.CanBuildFrom[CC[X],B,To2])(To, To2)
scala> partition(List(1,"two", 3)) {
| case i: Int => Left(i)
| case x => Right(x)
| }
res5: (List[Int], List[Any]) = (List(1, 3),List(two))
scala> partition(Vector(1,"two", 3)) {
| case i: Int => Left(i)
| case x => Right(x)
| }
res6: (scala.collection.immutable.Vector[Int], scala.collection.immutable.Vector[Any]) = (Vector(1, 3),Vector(two))
Только одно примечание: метод разбиения похож, но нам нужно захватить несколько типов:
X -> Оригинальный тип для предметов в коллекции.
A -> Тип элементов в левом разделе
B -> Тип элементов в правом разделе
CC -> «Конкретный» тип коллекции (Vector, List, Seq и т. Д.). Этот должен иметь более высокий род. Возможно, мы могли бы обойти некоторые проблемы с выводом типов (см. Ответ Адриана здесь: http://suereth.blogspot.com/2010/06/preserving-types-and-differing-subclass.html), но мне было лень;)
Кому -> Полный тип коллекции на левой стороне
To2 -> Полный тип коллекции с правой стороны
Наконец, забавные неявные параметры CanBuildFrom - это то, что позволяет нам создавать конкретные типы, такие как List или Vector, в общем. Они встроены во все основные библиотечные коллекции.
По иронии судьбы, вся причина магии CanBuildFrom в том, чтобы правильно обрабатывать битовые наборы. Поскольку я требую, чтобы CC был выше, мы получаем это забавное сообщение об ошибке при использовании раздела:
scala> partition(BitSet(1,2, 3)) {
| case i if i % 2 == 0 => Left(i)
| case i if i % 2 == 1 => Right("ODD")
| }
<console>:11: error: type mismatch;
found : scala.collection.BitSet
required: ?CC[ ?X ]
Note that implicit conversions are not applicable because they are ambiguous:
both method any2ArrowAssoc in object Predef of type [A](x: A)ArrowAssoc[A]
and method any2Ensuring in object Predef of type [A](x: A)Ensuring[A]
are possible conversion functions from scala.collection.BitSet to ?CC[ ?X ]
partition(BitSet(1,2, 3)) {
Я оставляю это открытым, чтобы кто-то мог исправить, если нужно! Я посмотрю, смогу ли я дать вам решение, которое работает с BitSet, после некоторой игры.