2009-06-29 7 views

Répondre

42

Voici une explication assez bonne:

http://www.codecommit.com/blog/scala/scala-collections-for-the-easily-bored-part-2

En utilisant la liste à titre d'exemple:

signature de carte est:

map [B](f : (A) => B) : List[B] 

et

de flatMap est
flatMap [B](f : (A) => Iterable[B]) : List[B] 

Ainsi flatMap prend un type [A] et renvoie un type itérable [B] et une carte prend un type [A] et renvoie un type [B]

Ceci vous donnera également une idée que flatmap va "s'aplatir" listes.

val l = List(List(1,2,3), List(2,3,4)) 

println(l.map(_.toString)) // changes type from list to string 
// prints List(List(1, 2, 3), List(2, 3, 4)) 

println(l.flatMap(x => x)) // "changes" type list to iterable 
// prints List(1, 2, 3, 2, 3, 4) 
+12

Il est intéressant de noter que 'flatMap {x => x}' est * précisément * équivalent à 'l.flatten' selon les axiomes monadiques. FlatMap est l'équivalent Scala de l'opération monadique 'bind' (>> = dans Haskell). Je trouve que c'est très utile sur les monades non-collections comme Option. Lorsqu'il est associé à des collections, il est très utile pour implémenter des "boucles de cartes imbriquées", renvoyant ainsi une collection. –

+0

Bien dit. Le chaînage d'Options est beaucoup mieux de travailler avec qu'un groupe d'instructions comme si (x! = Null et x.foo! = Null). http://blog.lostlake.org/index.php?/archives/50-The-Scala-Option-class-and-how-lift-uses-it.html en discute en détail – agilefall

+1

println (l.flatMap (x => x)) cela ne marche plus et flatMap doit être utilisé comme ça: http://aperiodic.net/phil/scala/s-99/p07.scala –

8

De scaladoc:

  • carte

Renvoie la iterable résultant d'application de la fonction f donnée à chaque élément de cette iterable.

  • flatMap

applique la fonction donnée f à chaque élément de cette iterable, puis concatène les résultats.

+0

Je cherche un peu plus d'analyse/explication. –

+0

OK, alors changez votre question pour être plus précis. Dites ce que vous savez déjà et ce dont vous avez besoin pour clarifier. – skaffman

+5

J'ai aimé votre commentaire snippy mieux. –

54

Ce qui précède est vrai, mais il y a une chose qui est à portée de main: flatMap tourne un List[Option[A]] en List[A], avec tout Option qui fore jusqu'à None, enlevé. C'est une percée conceptuelle clé pour aller au-delà de l'utilisation de null.

+3

Aw, c'est un autre truc sympa avec Option Je n'ai jamais pensé à ça. Je viens d'avoir une méthode retourner une liste de 1 ou plusieurs choses, n'a jamais vu la méthode 'Option.toList': Liste (certains (" foo "), aucun, certains (" bar ")). FlatMap (_.toList –

+0

Ou peut-être même mieux, utilisez 'Option.toIterator' avec la méthode de Tristan afin de ne pas parcourir toute la liste jusqu'à ce que cela soit nécessaire. – jkschneider

8
lines.map(line => line split "\\W+") // will return a list of arrays of words 
lines.flatMap(line => line split "\\W+") // will return a list of words 

Vous pouvez le voir mieux pour compréhensions:

for {line <- lines 
    word <- line split "\\W+"} 
yield word.length 

cela se traduit par:

lines.flatMap(line => line.split("\\W+").map(word => word.length)) 

Chaque itérateur à l'intérieur pour se traduire en "flatMap", à l'exception de la dernière un, qui est traduit en "carte".De cette façon, au lieu de renvoyer des collections imbriquées (une liste d'un tableau d'un tampon de bla, bla, bla), vous renvoyez une collection à plat. Une collection formée par les éléments étant cédés - une liste d'entiers, dans ce cas.