Каква е разликата между функциите map
и flatMap
на Iterable
?
scala Iterable#map срещу Iterable#flatMap
Отговори (5)
Ето едно доста добро обяснение:
http://www.codecommit.com/blog/scala/scala-collections-for-the-easily-bored-part-2
Използване на списък като пример:
Сигнатурата на картата е:
map [B](f : (A) => B) : List[B]
и flatMap е
flatMap [B](f : (A) => Iterable[B]) : List[B]
Така че flatMap приема тип [A] и връща итерируем тип [B], а map приема тип [A] и връща тип [B]
Това също така ще ви даде представа, че flatmap ще "изравнява" списъците.
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)
l flatMap { x => x }
е точно еквивалентно на l.flatten
според монадичните аксиоми. FlatMap е еквивалентът на Scala на монадичната bind
операция (››= в Haskell). Смятам, че е най-полезно за монади без колекции като Option. Когато е във връзка с колекции, той е най-полезен за внедряване на вложени цикли на картата, връщайки колекция като резултат.
- person Daniel Spiewak; 30.06.2009
Всичко по-горе е вярно, но има още едно полезно нещо: flatMap
превръща List[Option[A]]
в List[A]
, като всяко Option
, което се разбива до None
, се премахва. Това е ключов концептуален пробив за излизане отвъд използването на null
.
Option.toList
: List( Some( foo ), None, Some( bar ) ).flatMap( _.toList)
- person Tristan Juricek; 01.07.2009
Option.toIterator
с метода на Tristan, така че да не обикаляте целия списък, докато не е необходимо.
- person jkschneider; 06.06.2014
От scaladoc:
- карта
Връща итерируемия резултат от прилагането на дадената функция f към всеки елемент от този итерируем.
- плоска карта
Прилага дадената функция f към всеки елемент от този итерируем, след което обединява резултатите.
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
Можете да видите това по-добре в за разбиране:
for {line <- lines
word <- line split "\\W+"}
yield word.length
това се превежда в:
lines.flatMap(line => line.split("\\W+").map(word => word.length))
Всеки итератор вътре за ще бъде преведен в "flatMap", с изключение на последния, който се превежда в "карта". По този начин, вместо да връщате вложени колекции (списък от масив от буфер от бла, бла, бла), вие връщате плоска колекция. Колекция, образувана от елементите, които се предават -- в този случай списък с цели числа.
Вижте тук: http://www.codecommit.com/blog/scala/scala-collections-for-the-easily-bored-part-2
„Търсене на flatMap“ – там има наистина добро обяснение. (По принцип това е комбинация от "изравняване" и "карта" -- функции от други езици).