2016-03-22 18 views
1

Seq[(A, B)] var. Bu tür koleksiyonlara örtülü bir yöntem eklemek istedim, böylece Map[A, Seq[B]]'u geri almak için .toMultiMap yapabilirim.Genel olarak Scala koleksiyonlarını genişletme

implicit class PairsExtensions[A, B](t: Traversable[(A, B)]) { 
    def toMultiMap: Map[A, Traversable[B]] = t.groupBy(_._1).mapValues(_.map(_._2)) 
    } 

Ama şimdi sorun hep değerler için Traversable geri almak geçerli:

Bu

benim ilk girişimdi. Set[(A, B)].toMultiMap yaparsam Map[A, Set[B]]'u geri almak istiyorum. Çalışmazsa,

implicit class PairsExtensions2[A, B, Repr[_] <: Traversable[(A, B)]](t: TraversableLike[(A, B), Repr[(A, B)]]) { 
    def toMultiMap(implicit bf: CanBuild[B, Repr[B]]): Map[A, Repr[B]] = t.groupBy(_._1).mapValues(_.map(_._2)) 
    } 

Ama:

val m1: Map[Int, Set[String]] = Set.empty[(Int, String)] 
val m2: Map[Int, List[String]] = List.empty[(Int, String)] 

Bunu yapmanın yolu nedir

Yani, o zaman böyle bir şey denedi?

+0

m-ZL @ Maalesef açık olmak gerekirse, ilk girişim derler ve eserleri. İkinci snippet derlemiyor .. Sadece denememi yayınlıyordum. – pathikrit

+0

Sadece 2 kuruşum: “Set” üzerinde “.toMultiMap” için bir “Map” [A, Set [B] ') vermenin gerçekten mantıklı olup olmadığını yeniden düşünmek isteyebilirsiniz. Eski ve ikinci koleksiyonlardaki teklik oldukça farklı olacaktır. – Owen

+0

@Owen: Anladım. Sorunun amacı, özellikle .toMultiMap'in yapılması değil, Scala koleksiyonları için genel araçların nasıl yazılacağıdır. Hayal edebiliyorsunuz, 'List 'ı İstiyorum' Harita [A, Liste [B]]' geri döndü ve Seq's için, istiyorum Harita [A, Seq [B]] ' – pathikrit

cevap

4

Bunun peşinde olduğun şey olabileceğini düşünüyorum.

import scala.collection.generic.CanBuildFrom 
import scala.language.higherKinds 

implicit class PairsExtensions[A, B, C[X] <: Traversable[X]](t: C[(A, B)]) { 
    def toMultiMap(implicit cbf: CanBuildFrom[Nothing, B, C[B]]): Map[A, C[B]] = 
    t.groupBy(_._1).mapValues(_.map(_._2).to[C]) 
} 

Bu birkaç basit testler geçer:

scala> val m1: Map[Int, Set[String]] = Set.empty[(Int, String)].toMultiMap 
m1: Map[Int,Set[String]] = Map() 

scala> val m2: Map[Int, List[String]] = List.empty[(Int, String)].toMultiMap 
m2: Map[Int,List[String]] = Map() 

scala> Seq(('c',4),('x',2),('c',5)).toMultiMap 
res4: Map[Char,Seq[Int]] = Map(x -> Vector(2), c -> Vector(4, 5)) 
+0

Biraz teğet. Haritalar için benzer bir şey var mı? 'C [K, V] <: Harita [K, V]', 'C [V, Set [K]] 'üreten bir kapalı' invert 'eklemek istiyorum? – pathikrit

+0

Özellikle, bir Harita [V, Set [K]] 'nasıl üretileceğini biliyorum ama' CanBuildFrom' için 2 tür parametre alır bir 'C' için çalışmadım. – pathikrit

+0

Yorumlar bölümü, (ilgili olsa bile) yeni bir konu başlatmak için kötü bir yerdir, ancak bir 'Map' invertörüne sahibim. Bir Harita [K, Liste [V]] 'yi bir Harita [V, Liste [K]]' haline getirir. Bazı Harita 'm' için şunu deneyin:' m flatten {durum (k, vs) => vs.map ((_, k))} groupBy (_._ 1) mapValues ​​{_.map (_._ 2)} – jwvh