2009-06-29 14 views

risposta

42

Ecco una buona spiegazione:

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

Utilizzando lista come esempio: firma

del Map è:

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

e flatMap di è

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

Quindi flatMap accetta un tipo [A] e restituisce un tipo iterabile [B] e mappa assume un tipo [A] e restituisce un tipo [B]

Questo ti darà anche un'idea che flatmap si "appiattirà" elenchi.

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

È interessante notare che 'l flatMap {x => x}' è * precisamente * equivalente a 'l.flatten' secondo gli assiomi monadici. FlatMap è l'equivalente di Scala dell'operazione monadica 'bind' (>> = in Haskell). Trovo che sia più utile su monade non di raccolta come Opzione. Quando è in congiunzione con le raccolte, è molto utile per implementare "i loop della mappa nidificati", restituendo di conseguenza una collezione. –

+0

Ben detto. Il concatenamento di Opzioni è molto più efficace di un insieme di istruzioni come if (x! = Null e x.foo! = Null). http://blog.lostlake.org/index.php?/archives/50-The-Scala-Option-class-and-how-lift-uses-it.html discute questo in dettaglio – agilefall

+1

println (l.flatMap (x => x)) questo non funziona più e flatMap deve essere usato in questo modo: http://aperiodic.net/phil/scala/s-99/p07.scala –

8

Da scaladoc:

  • mappa

restituisce iterable risultante dall'applicazione della funzione data f per ogni elemento di questo iterabile.

  • flatMap

applica la funzione data f a ciascun elemento di questo iterabile, quindi concatena i risultati.

+0

Sto cercando un po 'più di analisi/spiegazione. –

+0

OK, quindi cambia la tua domanda in modo più specifico. Di 'ciò che già sai e di cosa hai bisogno di chiarire. – skaffman

+5

Mi è piaciuto il tuo commento snippy meglio. –

54

Quanto sopra è tutto vero, ma c'è una cosa che è a portata di mano: flatMap trasforma un List[Option[A]] in List[A], con qualsiasi Option che entra in profondità per None, rimosso. Questa è una svolta concettuale chiave per andare oltre l'utilizzo di null.

+3

Aw, questo è un altro bel trucco con Option Non ci ho mai pensato. Ho appena avuto un metodo per restituire un elenco di 1 o più elementi, mai visto il metodo 'Option.toList': Elenco (alcuni (" pippo "), Nessuno, Alcuni (" barra ")) .flatMap (_.toList) –

+0

O forse ancora meglio, usa "Option.toIterator" con il metodo di Tristan in modo da non scorrere l'intera lista finché necessario. – 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 

si può vedere questo meglio in espressioni for:

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

questo si traduce in:

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

Ogni iteratore all'interno per sarà tradotto in un "flatMap", tranne l'ultimo uno, che viene tradotto in una "mappa".In questo modo, invece di restituire le raccolte nidificate (una lista di una matrice di un buffer di blah, blah, blah), si restituisce una collezione piatta. Una raccolta formata dagli elementi che vengono resi: una lista di interi, in questo caso.