1

I have the following Map[String, Int]:

val m = Map[String, Int](
  "[LOGIN-011]" -> 0,
  "[LOGIN-103]" -> 3,
  "[LOGIN-222]" -> 10,
  "[ERROR-110]" -> 1,
  "[ERROR-012]" -> 3,
  ...
)

How to find duplicated values in the Map and print the values with List[String] as follows:

3 -> List("[LOGIN-103]", "[ERROR-012]")
Mario Galic
  • 47,285
  • 6
  • 56
  • 98
Dogil
  • 107
  • 1
  • 17
  • 1
    What have you tried? I will give you some clues: [`groupBy`](https://www.scala-lang.org/api/current/scala/collection/Map.html#groupBy[K](f:A=%3EK):scala.collection.immutable.Map[K,C]) - [`collect`](https://www.scala-lang.org/api/current/scala/collection/Map.html#collect[K2,V2](pf:PartialFunction[(K,V),(K2,V2)]):CC[K2,V2]) - [`keys`](https://www.scala-lang.org/api/current/scala/collection/Map.html#keys:Iterable[K]) - That should be enough. – Luis Miguel Mejía Suárez Jul 15 '19 at 19:06

2 Answers2

3

Try

m
  .toSeq
  .groupBy { case (key, value) => value }
  .collect { case (key, values: List[(String, Int)]) if values.size > 1 => (key, values.map(_._1))  }

which outputs

HashMap(3 -> List([ERROR-012], [LOGIN-103]))

Here is Luis' one-liner:

m.groupBy(_._2).collect { case (key, group: Map[String, Int]) if group.size > 1 => (key, group.keySet) }
Mario Galic
  • 47,285
  • 6
  • 56
  • 98
  • 1
    I would omit the `toSeq` and just call `keys` or `keySet` on the group. Also, since only duplicates matter, I would use `collect` instead of a `map` to filter in place. – Luis Miguel Mejía Suárez Jul 15 '19 at 19:06
  • @LuisMiguelMejíaSuárez I cannot seem to figure out how to use `keys` after `groupBy`, but I did figure out `collect`. – Mario Galic Jul 15 '19 at 19:28
  • 1
    One liner with possible typos since I am on my cellphone : `groupBy(_._2).collect { case (key, group) if (group.size > 1) => key -> group.keySet }` - **groupBy** on a **Map** returns another **Map** _(at least in 2.13)_. – Luis Miguel Mejía Suárez Jul 15 '19 at 19:32
  • 1
    No worries, actually I wouldn't add an answer. As I would prefer OP trying to solve it with the clues I gave it. - BTW, for anyone interested, on `2.13+` one can use `sizeIs > 1` which will be more efficient than `size > 1` as the first one does not compute all the size before returning _(I just learn that lol)_. – Luis Miguel Mejía Suárez Jul 15 '19 at 20:05
3

Following works in scala 2.13+ only

val map = Map (
  "[LOGIN-011]" -> 0,
  "[LOGIN-103]" -> 3,
  "[LOGIN-222]" -> 10,
  "[ERROR-110]" -> 1,
  "[ERROR-012]" -> 3
)

val duplicateValues = map.groupMap(_._2)(_._1).filterNot(_._2.sizeIs == 1)

//Map(3 -> List([ERROR-012], [LOGIN-103]))
Bogdan Vakulenko
  • 3,380
  • 1
  • 10
  • 25