Scala groupBy + выпуск карты - PullRequest
0 голосов
/ 05 июня 2018

Живой пример здесь: Пример Scastie

Я не понимаю, как это работает.У меня есть Seq кортежей, таких как:

val v = Seq(
  ("provider@test.com",2), 
  ("consumer@test.com",2), 
  ("provider@test.com",9), 
  ("provider@test.com",10)
)

Я хочу сгруппировать их так:

v.groupBy{ case(email, id) => id }

Это приводит к:

Map(
  2 -> List(
      (provider@test.com,2),
      (consumer@test.com,2)
  ), 
  10 -> List(
      (provider@test.com,10)
  ), 
  9 -> List(
      (provider@test.com,9)
  )
)

Что делаетпрекрасный смысл, но теперь, если я снова сопоставлю их так:

v.groupBy{ case(email, id) => id}.map{case(id, data) => data.head}.toSeq

Я ожидаю, что результат будет:

Vector((provider@test.com,2), (provider@test.com,10), (provider@test.com,9))

Однако я получаю:

Vector((provider@test.com,9))

Что не так?

Ответы [ 4 ]

0 голосов
/ 13 июля 2018

Это было неправильно, потому что вы вызвали метод map для объекта Map, как уже указывал Андрей Тюкин.Сначала преобразуйте его в список, а затем примените метод карты с соответствующей функцией преобразования, как показано ниже:
Это работает:

 v.groupBy{ case(email, id) => id}.toList.map(_._2.head)
0 голосов
/ 05 июня 2018

Когда вы делаете groupBy, вы получаете Map[Int, Seq[(String, Int)]].Метод map будет работать с каждой записью в вашем Map[Int, Seq[(String, Int)]].Если вы просто хотите работать со значениями, вы можете сделать

v.groupBy{ case(email, id) => id}.mapValues(...
0 голосов
/ 05 июня 2018

Это происходит, когда вы небрежно вызываете map на Map.В этом случае пары

  2 -> List(
      (provider@test.com,2),
      (consumer@test.com,2)
  ), 
  10 -> List(
      (provider@test.com,10)
  ), 
  9 -> List(
      (provider@test.com,9)
  )

преобразуются в пары

(provider@test.com,2)
(provider@test.com,10)
(provider@test.com,9)

, а затем снова вставляются в заново построенную карту, переопределяя значение 2 на 10, а затем на 9. Окончательный результатРезультатом является карта типа Map[String, Int] с единственной записью (provider@test.com,9), что, конечно, не то, что вы хотели.

Сделайте это вместо:

println(v.groupBy{ case(email, id) => id}.toSeq.map{case(id, data) => data.head})
0 голосов
/ 05 июня 2018

Это действительно немного сбивает с толку.Это происходит потому, что map на Map[K, V] также возвращает пару Map[K', V'], а ваши ключи одинаковы (почтовый адрес), вы получаете только одно значение.

Этого можно избежатьиспользуя .values, который возвращает Iterable значений в Map, а затем .map:

v
 .groupBy { case (_, id) => id }
 .values
 .map(_.head)
 .toList
...