/ / Czy jest jakaś różnica między spłaszczeniem a płaską mapą (tożsamością)? - Scala, funkcjonalne programowanie, flatmap

Czy jest jakaś różnica między spłaszczaniem a płaską mapą (tożsamością)? - Scala, funkcjonalne programowanie, flatmap

scala> List(List(1), List(2), List(3), List(4))
res18: List[List[Int]] = List(List(1), List(2), List(3), List(4))

scala> res18.flatten
res19: List[Int] = List(1, 2, 3, 4)

scala> res18.flatMap(identity)
res20: List[Int] = List(1, 2, 3, 4)

Czy jest jakaś różnica między tymi dwiema funkcjami? Kiedy należy używać jednego na drugim? Czy są jakieś kompromisy?

Odpowiedzi:

5 dla odpowiedzi № 1

Możesz wyświetlić flatMap(identity) tak jak map(identity).flatten. (Oczywiście nie jest to realizowane w ten sposób, ponieważ wymagałoby dwóch powtórzeń).

map(identity) daje tę samą kolekcję, więc w końcu jest taka sama jak tylko flatten.

Osobiście bym się trzymał flatten, ponieważ jest krótszy / łatwiejszy do zrozumienia i zaprojektowany, aby dokładnie to zrobić.


3 dla odpowiedzi № 2

Koncepcyjnie nie ma różnicy. Praktycznie, flatten jest bardziej wydajny i przekazuje wyraźniejsze intencje.

Ogólnie nie używasz identity bezpośrednio. Jest bardziej prawdopodobne, że w sytuacjach takich jak przekazanie go jako parametr lub ustawienie domyślne, kompilator może go zoptymalizować, ale ryzykujesz zbędne wywołanie funkcji dla każdego elementu.

Używałbyś flatMap kiedy musisz zrobić map (z funkcją inną niż identity) zaraz po nim flatten.


3 dla odpowiedzi nr 3

Koncepcyjnie nie ma różnicy w wyniku ... flatMap zabiera trochę więcej czasu, aby uzyskać ten sam wynik ...

Pokażę to bardziej praktycznie na przykładzie flatMap, map & następnie flatten i flatten

obiekt Test extends App { //flatmap println (timeElapsed (lista (lista (1, 2, 3, 4), lista (5, 6, 7, 8)). flatMap (tożsamość))) // mapuj i spłaszczaj println (timeElapsed (lista (lista (1, 2, 3, 4), lista (5, 6, 7, 8)) map (tożsamość) .flatten)) // spłaszcz się println (timeElapsed (lista (lista (1, 2, 3, 4), lista (5, 6, 7, 8)) spłaszcz))  / ** * czas, jaki upłynął * / def timeElapsed [T] (block: => T): T = { val start = System.nanoTime () val res = blok val totalTime = System.nanoTime - start println ("Czas, który upłynął:% 1d nano sekund" .format (totalTime)) res } }


Obie flatMap i flatten wykonywane z tym samym wynikiem po wielokrotnym powtarzaniu

Wniosek: flatten jest wydajny

Upływający czas: 2915949 nano sekund Lista (1, 2, 3, 4, 5, 6, 7, 8) Upływający czas: 1060826 nano sekund Lista (1, 2, 3, 4, 5, 6, 7, 8) Upływający czas: 81172 nano sekund Lista (1, 2, 3, 4, 5, 6, 7, 8)