Wie teile ich eine Sequenz durch ein Prädikat in zwei Listen auf?
Alternative: Ich kann meine eigene Methode verwenden filter
und filterNot
/ oder schreiben, aber gibt es keine allgemeinere (integrierte) Methode?
Wie teile ich eine Sequenz durch ein Prädikat in zwei Listen auf?
Alternative: Ich kann meine eigene Methode verwenden filter
und filterNot
/ oder schreiben, aber gibt es keine allgemeinere (integrierte) Methode?
Antworten:
Mit der partition
Methode:
scala> List(1,2,3,4).partition(x => x % 2 == 0)
res0: (List[Int], List[Int]) = (List(2, 4),List(1, 3))
_ % 2 == 0
.
Gut, das partition
war das, was Sie wollten - es gibt eine andere Methode, die auch ein Prädikat verwendet, um eine Liste in zwei Teile zu teilen : span
.
Die erste Partition fügt alle "wahren" Elemente in eine Liste und die anderen in die zweite Liste ein.
span fügt alle Elemente in eine Liste ein, bis ein Element "falsch" ist (in Bezug auf das Prädikat). Ab diesem Zeitpunkt werden die Elemente in die zweite Liste aufgenommen.
scala> Seq(1,2,3,4).span(x => x % 2 == 0)
res0: (Seq[Int], Seq[Int]) = (List(),List(1, 2, 3, 4))
Vielleicht möchten Sie einen Blick auf scalex.org werfen - hier können Sie die Scala-Standardbibliothek anhand ihrer Signatur nach Funktionen durchsuchen. Geben Sie beispielsweise Folgendes ein:
List[A] => (A => Boolean) => (List[A], List[A])
Sie würden Partition sehen .
Sie können auch foldLeft verwenden, wenn Sie etwas mehr benötigen. Ich habe gerade einen Code wie diesen geschrieben, als die Partition ihn nicht geschnitten hat:
val list:List[Person] = /* get your list */
val (students,teachers) =
list.foldLeft(List.empty[Student],List.empty[Teacher]) {
case ((acc1, acc2), p) => p match {
case s:Student => (s :: acc1, acc2)
case t:Teacher => (acc1, t :: acc2)
}
}
Ich weiß, dass ich vielleicht zu spät zur Party komme und es gibt spezifischere Antworten, aber Sie könnten sie gut gebrauchen groupBy
val ret = List(1,2,3,4).groupBy(x => x % 2 == 0)
ret: scala.collection.immutable.Map[Boolean,List[Int]] = Map(false -> List(1, 3), true -> List(2, 4))
ret(true)
res3: List[Int] = List(2, 4)
ret(false)
res4: List[Int] = List(1, 3)
Dies macht Ihren Code ein bisschen zukunftssicherer, wenn Sie die Bedingung in etwas nicht Boolesches ändern müssen.
Wenn Sie eine Liste in mehr als 2 Teile aufteilen und die Grenzen ignorieren möchten, können Sie Folgendes verwenden (ändern, wenn Sie nach Ints suchen müssen).
def split(list_in: List[String], search: String): List[List[String]] = {
def split_helper(accum: List[List[String]], list_in2: List[String], search: String): List[List[String]] = {
val (h1, h2) = list_in2.span({x: String => x!= search})
val new_accum = accum :+ h1
if (h2.contains(search)) {
return split_helper(new_accum, h2.drop(1), search)
}
else {
return accum
}
}
return split_helper(List(), list_in, search)
}
// TEST
// split(List("a", "b", "c", "d", "c", "a"), {x: String => x != "x"})
val (even, odd) = List(1,2,3,4).partition(x => x % 2 == 0)
ist eine Möglichkeit, das resultierende Tupel vonpartition
auf lesbare Weise zu zerstören .