2016-12-01 2 views
2

Я почесал голову энергично, чтобы понять логику, которая производит значение из() операции flatMap:Правильная интерпретация выражения flatmap Scala Map в

val ys = Map("a" -> List(1 -> 11,1 -> 111), "b" -> List(2 -> 22,2 -> 222)).flatMap(e => { 
    | println("e =" + e) 
    | (e._2) 
    | }) 
e =(a,List((1,11), (1,111))) 
e =(b,List((2,22), (2,222))) 
ys: scala.collection.immutable.Map[Int,Int] = Map(1 -> 111, 2 -> 222) 

Println ясно показывает, что flatMap принимает в одном входе из ввода Карта. Итак, e._2 - это список пар. Я не могу понять, что именно происходит после этого!

У меня отсутствует очень важный и тонкий шаг где-то. Пожалуйста, просветите меня.

ответ

4

Это можно рассматривать как:

Сначала мы отображаем:

val a = Map("a" -> List(1 -> 11,1 -> 111), "b" -> List(2 -> 22,2 -> 222)).map(e => e._2) 
// List(List((1, 11), (1, 111)), List((2, 22), (2, 222))) 

Тогда мы выравниваться:

val b = a.flatten 
// List((1, 11), (1, 111), (2, 22), (2, 222)) 

Затем мы конвертируем обратно на карту:

b.toMap 
// Map(1 -> 111, 2 -> 222) 

Поскольку карта не может иметь 2 значения f или 1, значение перезаписывается.


Действительно, что происходит в том, что flatMap преобразовывается в петлю следующим образом:

for (x <- m0) b ++= f(x) 

где:

  • m0 наша оригинальная карта

  • b - сборщик, который должен построить Map, aka, MapBuilder

  • е наша функция передается в flatMap (она возвращает List[(Int, Int)])

  • х является элементом в нашей оригинальной карте

++= функция принимает список, мы получили от вызова f(x), и звонит += на каждый элемент, чтобы добавить его на нашу карту. Для Map, += просто вызывает оператора + для Map, который обновляет значение, если ключ уже существует.

Наконец-то мы назовем result на нашем застройщике, который просто возвращает нам наш Map.

+1

Разработка через _map_, за которой следует _flatten_, была четкой. Фантастика. Этот момент пропустил меня как-то! Большое спасибо. @soote – Nirmalya

Смежные вопросы