Domanda

In Scala, chiamare groupBy () su una raccolta restituisce una Mappa dove i valori sono raccolte, ma voglio un MultiMap . Qual è il modo più semplice per eseguire la conversione? Posso evitare di creare un nuovo MultiMap e di copiare tutto?

È stato utile?

Soluzione

Penso che la risposta a " Devo creare un nuovo oggetto da mescolare in un tratto Scala? " è " Sì " ;. Puoi ridurre al minimo il dolore con il wrapping di oggetti e conversioni implicite.


Per il tuo problema specifico, non sono stato in grado di forzare groupBy (...) per restituire una mappa mutabile in set mutabili, che dovresti avvolgere con "MapProxy con MultiMap". Ma non sono troppe righe di codice per implementare la tua versione di " 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))

}

Addendum

Ecco un esempio del wrapping di una mappa esistente [String, Set [Int]] in una MultiMap senza copiare i valori:

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))
}

Nota che questo non può essere fatto sul risultato di groupBy (...) perché la mappa seme deve essere mutabile e groupBy (...) restituisce una mappa immutabile.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top