Gemäß einigen einige Vorschläge in den Kommentaren, schaute ich in CanBuildFrom, und das ist, was ich kam mit:
import scala.collection.IterableLike
import scala.collection.generic.CanBuildFrom
/** Filters `xs` to have only every nth element.
*/
def everyNth[A, It <: Iterable[A]]
(xs: It with IterableLike[A, It], n: Int, offset: Int = 0)
(implicit bf: CanBuildFrom[It, A , It]): It = {
val retval = bf()
retval ++= xs.zipWithIndex collect { case (x, i) if (i - offset) % n == 0 => x }
retval.result
}
Yay, es funktioniert !!!
Und es gibt NO Besetzung. Als solches funktioniert es sogar für Bereiche.
Allerdings muss man mit einem leeren Retval beginnen und dann "++ =" verwenden, um es aufzufüllen. Es erscheint ein wenig unelegant, also wenn jemand eine elegantere Lösung hat, bin ich ganz Ohr.
Hier ist eine weitere generische Funktion, die ich implementiert habe, die ein bisschen schwieriger als die oben genannten war, da der Rückgabetyp nicht der gleiche wie der Argumenttyp ist. I.e., Die Eingabe eine Folge von A
ist ‚s, aber der Ausgang ist eine Folge von (A, A)
‘ s:
def zipWithSelf[A, It[A] <: Iterable[A]]
(xs: It[A] with IterableLike[A, It[A]])
(implicit bf: CanBuildFrom[It[A], (A, A), It[(A, A)]]): It[(A, A)] = {
val retval = bf()
if (xs.nonEmpty) {
retval ++= xs zip xs.tail
retval.result
} else retval.result
}
Und hier ist ein andere:
/** Calls `f(x)` for all x in `xs` and returns an Iterable containing the indexes for
* which `f(x)` is true.
*
* The type of the returned Iterable will match the type of `xs`.
*/
def findAll[A, It[A] <: Iterable[A]]
(xs: It[A] with IterableLike[A, It[A]])
(f: A => Boolean)
(implicit bf: CanBuildFrom[It[A], Int, It[Int]]): It[Int] = {
val retval = bf()
retval ++= xs.zipWithIndex filter { p => f(p._1) } map { _._2 }
retval.result
}
Ich habe noch kein tiefes Verständnis für die "Like" -Typen und CanBuildFrom
, aber ich bekomme das Wesentliche. Und es ist in den meisten Fällen einfach genug, die Casting-Version einer generischen Funktion als ersten Durchlauf zu schreiben und dann die CanBuildFrom
und IterableLike
Boilerplate hinzuzufügen, um die Funktion allgemeiner und vollständig typsicher zu machen.
Ähnliche Frage, die 'CanBuildFrom' verwendet, um das Problem zu umgehen: [Funktion, die generisch einen Typ übernimmt und den gleichen Typ zurückgibt] (http://stackoverflow.com/questions/10019529/function-which-generically-takes- a-Typ-und-gibt den gleichen Typ zurück. Ich kann es nicht schaffen, mit dieser Frage zu arbeiten, jemand anderes? – sschaef
Ich bekam CanBuildFrom, um für meine Frage zu arbeiten, und legte die Lösung in eine Antwort. Sehen Sie die Antwort unten, wenn Sie neugierig sind. – Douglas
Schöne Antwort! Übrigens kannst du deine eigenen Antworten akzeptieren ... – sschaef