web-dev-qa-db-fra.com

Comment combiner filtre et carte en scala?

J'ai List[Int] dans Scala. La liste est List(1,2,3,4,5,6,7,8,9,10). Je veux filter la liste afin qu'elle ne comporte que des nombres pairs. Et je veux multiplier les nombres avec 2. Est-ce possible?

J'espère avoir clairement expliqué la question. Si vous avez des questions, n'hésitez pas à demander. Merci d'avance.

20
eddard.stark

Comme je le dis dans mon commentaire, collect devrait faire ce que vous voulez:

list.collect{
  case x if x % 2 == 0 => x*2
}

La méthode collect vous permet à la fois de spécifier un critère sur les éléments correspondants (filter) et de modifier les valeurs qui correspondent (map).

Et comme @TravisBrown l'a suggéré, vous pouvez également utiliser flatMap, en particulier dans des situations où la condition est plus complexe et ne convient pas comme condition de garde. Quelque chose comme ça pour votre exemple:

list.flatMap{
  case x if x % 2 == 0 => Some(x*2)
  case x => None
}
41
cmbaxter

A pour la compréhension (qui se déroule en interne dans une combinaison de map et withFilter) comme suit,

for (x <- xs if x % 2 == 0) yield x*2

À savoir

xs.withFilter(x => x % 2 == 0).map(x => x*2)
6
elm

Comme @cmbaxter l'a dit, collect convient parfaitement à vos besoins. L'autre bonne chose à propos de collect, c'est qu'il calcule le type résultant si vous filtrez par classe: 

scala> trait X
// defined trait X

scala> class Foo extends X
// defined class Foo

scala> class Bar extends X
// defined class Bar

scala> val xs = List(new Foo, new Bar, new Foo, new Bar)
// xs: List[X] = List(Foo@4cfa8227, Bar@78226c36, Foo@3f685162, Bar@11f406f8)

scala> xs.collect { case x: Foo => x }
// res1: List[Foo] = List(Foo@4cfa8227, Foo@3f685162)

Au pair, le filtre ne peut pas être aussi intelligent (voir List[Foo] vs List[X]): 

scala> xs.filter { case x: Foo => true; case _ => false }
// res3: List[X] = List(Foo@4cfa8227, Foo@3f685162)
1
om-nom-nom

Que diriez-vous d'un bon vieux pli?

xs.foldLeft(List[Y]()) { (ys, x) => 
    val z = calculateSomethingOnX(x)
    if (someConditionOnZ(z)) 
        Y(x, z) :: ys
    else 
        ys
}
0
F. P. Freely

J'ai tendance à aimer l'approche du filtre.

val list1 = List(1,2,3,4,5,6,7,8,9,10)
list1.filter(x => x%2 == 0).map(_*2)
0
Dean Sha

Cela devrait faire le travail pour vous:

Filtrez d'abord lorsque la condition est p % 2 == 0 (pour obtenir uniquement des nombres pairs).

Et utilisez ensuite map pour multiplier ces nombres pairs par 2.

var myList = List(1,2,3,4,5,6,7,8,9,10).filter(p => p % 2 == 0).map(p => {p*2})
0
Cacho Santa