Scala: некоторые вопросы по flatMap и карте - PullRequest
0 голосов
/ 16 мая 2018

У меня есть фрагмент кода Scala: https://scastie.scala -lang.org / 1ey5T9lWQVOAozLoGVJthw

val days = List((1, (2, "a")), (1, (3, "b")), (1, (1, "c")), (2, (1, "aa")), (2, (2, "bb")))

println(days)

println(days.groupBy(_._1))
val r = days.groupBy(_._1).map(t => {
  println(s"t = $t, t._1 = ${t._1} t._2 = ${t._2} t._2.map(_._2) = ${t._2.map(_._2).toMap}")
  t._1 -> t._2.map(_._2).toMap
})


println(s"r = $r")

val rr = r.flatMap {
  case (k, v) => Some(k, v)
}

println(rr)

val rrr = r.map {
  case (k, v) => Some(k, v)
}

println(rrr)

Вывод после запуска программы:

List((1,(2,a)), (1,(3,b)), (1,(1,c)), (2,(1,aa)), (2,(2,bb)))
Map(2 -> List((2,(1,aa)), (2,(2,bb))), 1 -> List((1,(2,a)), (1,(3,b)), (1,(1,c))))
t = (2,List((2,(1,aa)), (2,(2,bb)))), t._1 = 2 t._2 = List((2,(1,aa)), (2,(2,bb))) t._2.map(_._2) = Map(1 -> aa, 2 -> bb)
t = (1,List((1,(2,a)), (1,(3,b)), (1,(1,c)))), t._1 = 1 t._2 = List((1,(2,a)), (1,(3,b)), (1,(1,c))) t._2.map(_._2) = Map(2 -> a, 3 -> b, 1 -> c)
r = Map(2 -> Map(1 -> aa, 2 -> bb), 1 -> Map(2 -> a, 3 -> b, 1 -> c))
Map(2 -> Map(1 -> aa, 2 -> bb), 1 -> Map(2 -> a, 3 -> b, 1 -> c))
List(Some((2,Map(1 -> aa, 2 -> bb))), Some((1,Map(2 -> a, 3 -> b, 1 -> c))))

У меня есть несколько вопросов:

1, почему rr и rrr различны?

(1) Почему rr это Map, а rrr это List? Я понимаю, rrr это List. map будет работать с каждой парой ключ-значение и, наконец, вернет List. Я прав? Но почему flatMap возвращает Map?

(2) почему Some in rrr? Some используется для фильтрации None?

2, В flatMap, Some(k, v) будет преобразовано в k->v?

3, В flatMap, Some(a -> (b -> c)) будут преобразованы в (a, (b, c))?

Что касается 2 и 3, я запутался, почему кортеж и карта перепутались? Я могу ошибаться.

Я новичок в Скале. Даже если я читаю некоторые уроки, у меня все еще слишком много путаницы. В большинстве учебных пособий приводятся примеры flatMap из List, Seq.

Любая помощь приветствуется. Спасибо

1 Ответ

0 голосов
/ 16 мая 2018

Тип результата большинства методов сбора, таких как map, flatMap и т. Д., Зависит от типа результата функции, которую мы передаем ему.

Это определяется CanBuildFrom неявные значения.

Учитывая, что существует CanBuildFrom экземпляр для Map типов, основанный на Tuple2.Другими словами, если вы возвращаете Tuple2 из функции, переданной в map из Map, то результатом также будет Map, но если вы возвращаете что-то, отличное от Tuple2, функция map выбираетследующий конкретный CanBuildFrom, основанный на Iterable.

В случае rr, flatMap в основном вызывает flatten, а затем map.Во время операции flatten значение Option[Tuple2[A, B]] сводится к Tuple2[A, B], поэтому Tuple2 передается в функцию map, и в результате получается Map.

В случаеrrr, результат не Tuple2, а Option[Tuple2[A, B]], поэтому он не может использовать CanBuildFrom, определенный Map при GenMapFactory.scala.

Чтобы добавить больше к этому, попробуйте следующий код, и результат будет Map

val r3 = r.map {
  case (k, v) => (k, v)
}

println(r3) //r3 is a Map not a List
...