133 votes

Comment diviser une liste en deux morceaux avec un prédicat?

Comment diviser une liste en deux listes par un prédicat?

Peut-être que j'ai manqué quelque chose, mais je ne pouvais pas trouver une fonction intégrée dans l'API Scala. Ou n'y en a-t-il pas?

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)?

213voto

om-nom-nom Points 33691

En utilisant la méthode partition :

 scala> List(1,2,3,4).partition(x => x % 2 == 0)
res0: (List[Int], List[Int]) = (List(2, 4),List(1, 3))
 

147voto

Daniel C. Sobral Points 159554

Bien qu' partition a été la chose que tu voulais, il y a une autre méthode qui utilise également un prédicat de diviser la liste en deux: span.

La première, partition va mettre tous les "vrais" des éléments dans une liste, et les autres dans la deuxième liste. D'autre part, span va mettre tous les éléments dans une liste jusqu'à ce qu'un élément est "faux". À partir de ce moment, elle va mettre les éléments dans la deuxième liste.

Depuis que la question est assez ambigu (à part le commentaire à propos de filter/filterNot), je laisse cette réponse ici parce que d'autres peuvent avoir besoin du second.

17voto

oxbow_lakes Points 70013

Vous voudrez peut-être jeter un oeil sur scalex.org - il vous permet de rechercher des fonctions dans la bibliothèque standard scala en fonction de leur signature. Par exemple, tapez ce qui suit:

 List[A] => (A => Boolean) => (List[A], List[A])
 

Vous verriez la partition .

14voto

Brian Points 1265

Vous pouvez également utiliser foldLeft si vous avez besoin de quelque chose d'un peu plus. Je viens d'écrire du code comme celui-ci quand 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)
    }
  }
 

0voto

Matt Points 31

Si vous souhaitez scinder une liste en plus de 2 morceaux et ignorer les limites, vous pouvez utiliser quelque chose comme ceci (à modifier si vous devez 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"})
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X