문제

Scala에서 "직사각형"컬렉션 컬렉션 컬렉션, 예 :지도 목록, 목록의지도, 맵의지도, 목록 세트, 목록의 맵, 컬렉션 이후의지도 등의 목록, 특정 도메인으로부터 공동 도메인으로의 매핑으로 균일하게 볼 수 있습니다 (예 : 목록 [A] / ARRATE [A]은 int 도메인에서 공동 도메인으로의 매핑, [a]는 매핑입니다) A 도메인에서 부울 공동 도메인 등에서), Transpose 작동을 수행하기 위해 깨끗하고 일반 함수를 작성하고 싶습니다 (예 : 목록의지도의지도를 옮기는 맵 목록에 대한 목록 맵). 그러나 () 운영자가 아닌 경우에도 문제가 있기 때문에 스칼라는 추상적으로 매핑으로 추상적으로 컬렉션을 볼 수있는 통합 API가있는 것 같습니다.

다음과 같이 각 유형의 컬렉션 컬렉션의 각 유형에 대해 별도의 지배 작성을 종료합니다.

def transposeMapOfLists[A,B]( mapOfLists: Map[A,List[B]] ) : List[Map[A,B]] = {
  val k = ( mapOfLists keys ) toList
  val l = ( k map { mapOfLists(_) } ) transpose;
  l map {  v => ( k zip v ) toMap }
}

def transposeListOfMaps[A,B]( listOfMaps: List[Map[A,B]]) : Map[A,List[B]] = {
  val k = ( listOfMaps(0) keys ) toList
  val l = ( listOfMaps map { m => k map { m(_) } } ) transpose;
  ( k zip l ) toMap
}

def transposeMapOfMaps[A,B,C]( mapOfMaps: Map[A,Map[B,C]] ) : Map[B,Map[A,C]] = {
  val k = ( mapOfMaps keys ) toList
  val listOfMaps = k map { mapOfMaps(_) }
  val mapOfLists = transposeListOfMaps( listOfMaps )
  mapOfLists map { p => ( p._1, ( k zip p._2 ) toMap ) }
}
.

누군가가 이러한 메소드를 하나의 일반 수집 컬렉션을 조정하는 하나의 일반적인 콜렉션으로 통합 할 수 있습니까? 그것은 또한 또한 나를 도울 것입니다 (그리고 나는 다른 사람들이 프로세스에서 유용한 스칼라 기능을 배우십시오.

ps : 예외 처리를 무시하고 입력 수집 콜렉션이 직사각형, 즉 모든 내부 컬렉션의 도메인 요소가 동일한 세트를 구성합니다.

도움이 되었습니까?

해결책

유형 클래스를 사용하여 다음과 같은 지저분한 버전을 많이 정리할 수는 있지만 빠른 개념으로 작동합니다.나는 종속적 인 방법 유형없이 리턴 타입을 쉽게 얻을 수있는 쉬운 방법이 보이지 않습니다 (가능합니다). 따라서 -Xexperimental를 사용해야합니다.

trait Mapping[A, B, C] {
  type M[D] <: PartialFunction[A, D]
  def domain(c: C): Seq[A]
  def fromPairs[D](ps: Seq[(A, D)]): M[D]
  def codomain(c: C)(implicit ev: C <:< PartialFunction[A, B]) =
    domain(c).map(c)
  def toPairs(c: C)(implicit ev: C <:< PartialFunction[A, B]) =
    domain(c).map(a => (a, c(a)))
}

implicit def seqMapping[A, B <: Seq[A]] = new Mapping[Int, A, B] {
  type M[C] = Seq[C]
  def domain(c: B) = 0 until c.size
  def fromPairs[C](ps: Seq[(Int, C)]) = ps.sortBy(_._1).map(_._2)
}

implicit def mapMapping[A, B, C <: Map[A, B]] = new Mapping[A, B, C] {
  type M[D] = Map[A, D]
  def domain(c: C) = c.keys.toSeq
  def fromPairs[D](ps: Seq[(A, D)]) = ps.toMap
}

def transpose[A, B, C, M, N](m: M)(implicit
  pev: M <:< PartialFunction[A, N],
  qev: N <:< PartialFunction[B, C],
  mev: Mapping[A, N, M],
  nev: Mapping[B, C, N]
) = nev.fromPairs(nev.domain(mev.codomain(m).head).map(b =>
    b -> mev.fromPairs(mev.toPairs(m).map { case (a, c) => a -> c(b) })
))
.

및 이제 일부 테스트 :

scala> println(transpose(List(Map("a" -> 1, "b" -> 13), Map("b" -> 99, "a" -> 14))))
Map(a -> Vector(1, 14), b -> Vector(13, 99))

scala> println(transpose(Map('a' -> List(1, 2, 3), 'z' -> List(4, 5, 6))))
Vector(Map(a -> 1, z -> 4), Map(a -> 2, z -> 5), Map(a -> 3, z -> 6))

scala> println(transpose(Map("x" -> Map(4 -> 'a, 99 -> 'z), "y" -> Map(4 -> 'b, 99 -> 's))))
Map(4 -> Map(x -> 'a, y -> 'b), 99 -> Map(x -> 'z, y -> 's))
.

원하는대로 작동합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top