2011-02-15 4 views
7

내가지도의지도의지도로 튜플의 순서를 변환하는 더 간결한 방법이 필요합니다 ... 서명으로 나는 Tuple4의 경우에 얻을 :4 튜플 순서에지도

def tuple4Seq2MapOfMaps[A,B,C,D](seq: Seq[(A,B,C,D)]): Map[A,Map[B,Map[C,D]]] 

다음 코드는 내가 (D 임의에 유형 A)와 stucked, 내 최근 추한 코드를 보여줍니다

type A = Int 
type B = Double 
type C = String 
type D = Boolean 
val tupleSeq = Seq[(A,B,C,D)](
    (1,1.0D,"a",true), 
    (1,1.0D,"b",true), 
    (1,1.0D,"c",false) 
) 
val x = tupleSeq.groupBy{ _._1 }.map{ case (k,s) => (k,s.map{ x => (x._2,x._3,x._4) }) } 
val y = x.map{ case (k,s) => (k,s.groupBy{_._1}.map{ case (k,s) => (k,s.map{ x => (x._2,x._3) }) }) } 
val z = y.map{ case (k1,m) => (k1,m.map{ case (k2,s1) => (k2,s1.groupBy{_._1}.map{ case (k3,s2) => (k3,s2.map{ _._2 }.head) }) }) } 

val m = z(1)(1.0D) 
println(m("b")) 

주,736,472에서 head의 사용.

Tuple4에 대해서만 더 간결한 방법을 사용하는 것이 좋지만이 방법을 (N> = 2)으로 일반화하는 방법도 흥미 롭습니다.

거기에 누군가의 마음에 좋은 접근법이 있습니까?

감사합니다.

답변

8

이다와 내가 올 수있는 가장 높은 인수에 대응의 튜플에

tupleSeq.groupBy(_._1). 
    mapValues(_.groupBy(_._2). 
    mapValues(_.groupBy(_._3). 
     mapValues{ case Seq(p) => p._4 })) 

일반화를 매우 straightfoward입니다 ... 단지 추가 mapValues의 추가 중첩 된 응용 프로그램 (_groupBy (_. n)) ... 그리고 그에 따라 최종 패턴 일치를 조정하십시오 ...

임의 ar의 튜플에 대한 함수로 이것을 완전히 일반화하십시오 HList를 사용하여 가능할 수도 있지만, 여기서는 필요한 것보다 훨씬 더 많은 헤비급 해결책이 될 것입니다. 이 공격의 라인을 질문자 (또는 다른 주석가 ;-)를위한 운동으로 남겨 둘 것입니다.

+0

아주 좋은 해결책입니다! 고맙습니다! –

+0

추가 사항 :'mapValues'가 뷰를 반환한다는 사실을 알고 있어야합니다. Rex Kerr의 멋진 답변을 참조하십시오 : http://stackoverflow.com/questions/5433578/subsetof-versus-forall-contains –

1

나는 튜플에 implicits을 건의 할 것입니다 :

implicit def Tup3Cut[A,B,C](tup: (A,B,C)) = new { 
    def decapitate = (tup._2,tup._3) 
} 
implicit def Tup4Cut[A,B,C,D](tup: (A,B,C,D)) = new { 
    def decapitate = (tup._2,tup._3,tup._4) 
} 

val tupleSeq = Seq((1,1d,"a",true),(1,1d,"b",true),(1,1d,"c",false),(1,2d,"c",true)) 

tupleSeq.groupBy(_._1).mapValues(
    _.map(_.decapitate).groupBy(_._1).mapValues(_.map(_.decapitate).toMap) 
)