Este é um caso de uso bastante comum com o qual frequentemente me deparo, especialmente como perguntas de novatos no scala.
É por isso que quero compartilhar esta dica realmente básica.
Suponha que temos um Map
de Int -> Int
valores, gerados aleatoriamente
val intMap = (for (id <- 1 to 100) yield (id, Random.nextInt(10))).toMap
> intMap: scala.collection.immutable.Map[Int,Int] = Map(69 -> 2, 88 -> 8, 5 -> 3, 10 -> 9, ... )
As coleções Scala permitem agrupar as entradas que especificam os critérios de agrupamento com uma expressão lambda.
Portanto, podemos agrupar nosso mapa por valores distintos e, em seguida, contar as instâncias de cada valor mapeando nos submapas resultantes obtendo seu tamanho.
No código, isso significa
val occurrences = intMap groupBy {case (id, value) => value} mapValues (_.size)
> occurrences: scala.collection.immutable.Map[Int,Int] = Map(0 -> 10, 5 -> 8, 1 -> 11, 6 -> 10, 9 -> 9, 2 -> 13, 7 -> 9, 3 -> 10, 8 -> 14, 4 -> 6)
Ou usando uma sintaxe mais curta
val occurrences = intMap groupBy (_._2) mapValues (_.size)
Vamos explorar isso passo a passo
quando nós
groupBy
( docs ), obtemos outro mapa cujas chaves são os valores encontrados emintMap
, e cujos valores são um “submapa” deintMap
, que contém apenas as entradas relevantesagora só precisamos transformar cada submapa com
mapValues
( docs ), obtendo seu tamanho correspondente, para saber quantas ocorrências havia para cada valor no originalintMap
Digamos que você queira saber quantos 5
s havia no mapa
val howmanyfives = occurrences(5)
> howmanyfives: Int = 8
Ou, melhor ainda, de uma forma segura
val howmanypossiblyfive = occurrences get 5
> howmanypossiblyfive: Option[Int] = Some(8)
Aproveite o seu histagrama.