Como faço para dividir uma sequência em duas listas por um predicado?
Alternativa: Eu posso usar filter
e filterNot
, ou escrever meu próprio método, mas não existe um método mais geral (integrado) melhor?
Como faço para dividir uma sequência em duas listas por um predicado?
Alternativa: Eu posso usar filter
e filterNot
, ou escrever meu próprio método, mas não existe um método mais geral (integrado) melhor?
Respostas:
Usando o partition
método:
scala> List(1,2,3,4).partition(x => x % 2 == 0)
res0: (List[Int], List[Int]) = (List(2, 4),List(1, 3))
_ % 2 == 0
.
Bem que partition
foi a coisa que você queria - não há outro método que também utiliza um predicado para dividir uma lista em duas: span
.
O primeiro, partição , colocará todos os elementos "verdadeiros" em uma lista e os outros na segunda lista.
span irá colocar todos os elementos em uma lista até que um elemento seja "falso" (em termos do predicado). Desse ponto em diante, ele colocará os elementos da segunda lista.
scala> Seq(1,2,3,4).span(x => x % 2 == 0)
res0: (Seq[Int], Seq[Int]) = (List(),List(1, 2, 3, 4))
Você pode querer dar uma olhada em scalex.org - ele permite que você pesquise na biblioteca padrão do scala por funções por sua assinatura. Por exemplo, digite o seguinte:
List[A] => (A => Boolean) => (List[A], List[A])
Você veria partição .
Você também pode usar o foldLeft se precisar de algo um pouco mais. Acabei de escrever um código como este quando a partição não o cortou:
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)
}
}
Sei que posso chegar atrasado para a festa e há respostas mais específicas, mas você poderia fazer bom uso 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)
Isso torna seu código um pouco mais preparado para o futuro se você precisar alterar a condição para algo não booleano.
Se você quiser dividir uma lista em mais de 2 partes e ignorar os limites, pode usar algo como isto (modifique se precisar pesquisar por ints)
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)
é uma maneira de destruir a tupla resultante departition
de uma forma legível.