Ich wollte nur mit einem „allgemeineren“ -Version auf mkneissl Antwort erweitern, die auf vielen verschiedenen Sammlungen in der Bibliothek arbeiten sollten:
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))
Nur eine Anmerkung: die Trennwand Methode ist ähnlich, aber wir müssen ein paar Arten erfassen:
X -> Der ursprüngliche Typ für Elemente in der Sammlung.
A -> Die Art der Elemente in der linken Trennwand
B -> Die Art der Elemente in der richtigen Partition
CC -> Die "spezifische" Art der Sammlung (Vector, List, Seq etc.) Diese muss höher-kinded sein. Wir könnten wahrscheinlich einige Typ-Inferenz-Probleme umgehen (siehe Adrian Antwort hier: http://suereth.blogspot.com/2010/06/preserving-types-and-differing-subclass.html), aber ich fühlte mich faul;)
To -> Die komplette Art der Sammlung auf der linken Seite
To2 -> Der vollständige Typ der Sammlung auf der rechten Seite
Schließlich sind die lustigen "CanBuildFrom" impliziten Parameter, die uns erlauben, bestimmte Typen, wie List oder Vector, generisch zu konstruieren. Sie sind in alle zentralen Bibliothekssammlungen integriert.
Ironischerweise ist der Grund für die CanBuildFrom-Magie, BitSets korrekt zu behandeln. Weil ich CC erfordern höhere kinded sein, bekommen wir diese Meldung Spaß Fehler, wenn Partition mit:
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)) {
Ich gehe für jemanden offen, dies zu beheben, wenn nötig! Ich werde sehen, ob ich Ihnen eine Lösung geben kann, die nach einiger Zeit mit BitSet funktioniert.
Schade, dass 'a' vom Typ' List [Any] 'ist gegenüber' List [Int] '... – huynhjl
Das liegt nur daran, dass' x' ist. Siehe @ abhin4vs Antwort. –
Ich verstehe, warum es 'List [Any]' ist, es ist nur, dass 'collect', wie in der Frage verwendet, eine' List [SomeClass] 'zurückgibt, während die Partition diese Information verliert. – huynhjl