Это связано с тем, как синтаксис понимания for
преобразуется компилятором в серию вызовов методов.map
, flatMap
и withFilter
предназначены для перестановок for
пониманий.Это очень мощный и общий способ, поскольку он позволяет синтаксису работать с произвольными типами.Есть еще кое-что, например, неявное CanBuildFrom
, но, по сути, отображение Map
в Iterable[Tuple[A, B]]
дает Map[A, B]
.scala.collection.IterableOnce[(K2,V2)]):CC[K2,V2]" rel="nofollow noreferrer"> Сигнатура фактически перегружена для Map
, чтобы обеспечить такое поведение
Перевод выглядит примерно так
val thisIsMap1 = dummy.flatMap { x =>
x._2.keys.map { y =>
(x._1, y)
}
}
Смотрите это fiddle
Чтобы получить требуемый список, мы можем написать
val thisIsMap = (for (x <- dummy; y <- x._2.keys) yield (x._1, y)).toList
Однако, если мы рассмотрим то, что мы узнали о for
пониманиях, мы можем написать его более элегантно как
val thisIsMap = for (x <- dummy.toList; y <- x._2.keys) yield (x._1, y)
В вышеизложенном мы использовали само поведение, которое запутало исходный код, сделав вывод, что понимание for
над List
приведет к List
.
Однако , обратите внимание на разницу между преобразованием источника в List
и преобразованием полученной карты в List
после понимания.
Если мыпозвонив toList
по источнику (dummy
), мы получим List((1,2), (1,4), (6,7))
, тогда как, если мы вызовем его по результату, мы получим List((1,4), (6,7))
, по понятным причинам, поэтому выбирайте осторожно и осознанно.