Comment diviser une séquence en deux listes par un prédicat?
Alternative: je peux utiliser filter
et filterNot
, ou écrire ma propre méthode, mais n'y a-t-il pas une meilleure méthode plus générale (intégrée)?
Comment diviser une séquence en deux listes par un prédicat?
Alternative: je peux utiliser filter
et filterNot
, ou écrire ma propre méthode, mais n'y a-t-il pas une meilleure méthode plus générale (intégrée)?
Réponses:
En utilisant la partition
méthode:
scala> List(1,2,3,4).partition(x => x % 2 == 0)
res0: (List[Int], List[Int]) = (List(2, 4),List(1, 3))
_ % 2 == 0
.
Bon qui partition
était la chose que vous vouliez - il y a une autre méthode qui utilise également un prédicat de diviser une liste en deux: span
.
Le premier, partition mettra tous les éléments "vrais" dans une liste, et les autres dans la deuxième liste.
span mettra tous les éléments dans une liste jusqu'à ce qu'un élément soit "faux" (en termes de prédicat). À partir de là, il mettra les éléments dans la deuxième liste.
scala> Seq(1,2,3,4).span(x => x % 2 == 0)
res0: (Seq[Int], Seq[Int]) = (List(),List(1, 2, 3, 4))
Vous voudrez peut-être jeter un œil à scalex.org - il vous permet de rechercher dans la bibliothèque standard scala des fonctions par leur signature. Par exemple, tapez ce qui suit:
List[A] => (A => Boolean) => (List[A], List[A])
Vous verriez une partition .
Vous pouvez également utiliser foldLeft si vous avez besoin de quelque chose d'un peu plus. Je viens d'écrire un code comme celui-ci lorsque la partition ne l'a pas coupé:
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)
}
}
Je sais que je suis peut-être en retard pour la fête et il y a des réponses plus précises, mais vous pourriez faire bon usage de 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)
Cela rend votre code un peu plus évolutif si vous devez changer la condition en quelque chose de non booléen.
Si vous voulez diviser une liste en plus de 2 morceaux et ignorer les limites, vous pouvez utiliser quelque chose comme ça (modifiez si vous avez besoin de rechercher des entiers)
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)
est un moyen de détruire le tuple résultant departition
de manière lisible.