我想进一步扩展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 -> 集合的“特定”类型(向量、列表、序列等)。这个必须是高级别的。我们可能可以解决一些类型推断问题(参见Adrian在这里的回答:http://suereth.blogspot.com/2010/06/preserving-types-and-differing-subclass.html),但我感到有点懒 ;)
To -> 左侧集合的完整类型
To2 -> 右侧集合的完整类型
最后,有趣的“CanBuildFrom”隐式参数允许我们以通用方式构建特定类型,如List或Vector。它们内置于所有核心库集合中。
具有讽刺意味的是,CanBuildFrom魔法的全部原因是正确处理BitSet。因为我要求CC是高级别的,所以当使用partition时,我们得到这个有趣的错误消息:
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后仍然有效的解决方案。
x
是这样的。参见 @abhin4v 的回答。 - Alexey RomanovList[Any]
,只是问题中使用的collect
会返回一个List[SomeClass]
,而partition
会丢失这些信息。 - huynhjl