Pergunta

Em Scala, chamando groupBy() em uma coleção retorna uma Map onde os valores são coleções, mas eu quero uma MultiMap. Qual é a maneira mais fácil de fazer a conversão? Posso evitar a criação de um novo MultiMap e copiar tudo de novo?

Foi útil?

Solução

Eu acho que a resposta à pergunta "Eu tenho que criar um novo objeto para misturar em uma Scala traço?" é sim". Você pode minimizar a dor alguma com objetos de acondicionamento e conversões implícitas.


Para o seu problema específico, eu era incapaz de coagir groupBy (...) para retornar um mapa mutável para conjuntos mutáveis, o que você precisa para envolvê-lo com "MapProxy com MultiMap". Mas, não é muitas linhas de código para implementar sua própria versão de "groupBy":

package blevins.example

object App extends Application {

  implicit def multiMapable[B](c: Iterable[B]) = new {
    def groupByMM[A](f: B => A) = {
      import scala.collection.mutable._
      val ret = new HashMap[A,Set[B]] with MultiMap[A,B]
      for (e <- c) { ret.addBinding(f(e), e) }
      ret
    } 
  }

  val c = List(1,2,3,4,5,6,7,8,9)
  val mm = c.groupByMM { i => if (i < 5) "alpha" else "beta" }
  mm.addBinding("alpha",12)
  println(mm) // Map(beta -> Set(5, 7, 6, 9, 8), alpha -> Set(3, 1, 4, 2, 12))

}

Adenda

Aqui está um exemplo de envolver um já existente Mapa [String, Set [Int]] em um MultiMap sem copiar os valores:

object App extends Application {
  import scala.collection.mutable._
  val seed: Map[String,Set[Int]] = Map("even" -> Set(2,4,6), "odd" -> Set(1,3,5))

  val multiMap = new MapProxy[String,Set[Int]] with MultiMap[String,Int] {
    val self = seed
  }

  multiMap.addBinding("even", 8)
  println(multiMap) // Map(odd -> Set(5, 3, 1), even -> Set(6, 8, 4, 2))
}

Note que isso não pode ser feito sobre o resultado da groupBy (...) porque o mapa semente é necessário para ser mutável e groupBy (...) retorna um mapa imutável.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top