2011-02-15 27 views
7

Tôi cần một cách ngắn gọn hơn để chuyển đổi một chuỗi các tuples thành một bản đồ bản đồ bản đồ ... Là một chữ ký tôi nhận được trong trường hợp Tuple4:4-tuple Chuỗi Để Bản đồ Maps của Maps

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

các mã sau đây cho thấy gần đây đang xấu xí của tôi, tôi stucked với (loại A-D tùy ý):

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

Lưu ý việc sử dụng head tại val z.

Thật tuyệt khi có cách ngắn gọn hơn chỉ cho Tuple4, nhưng thú vị hơn nữa là cách khái quát hóa điều này thành TupleN (N> = 2).

Có cách tiếp cận tốt đẹp trong tâm trí ai đó không?

Cảm ơn bạn!

Trả lời

8

Điều tốt nhất tôi có thể đưa ra là,

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

Khái quát để tuples của arity cao hơn khá straightfoward ... chỉ cần thêm thêm các ứng dụng lồng nhau của mapValues ​​(_groupBy (_._ n). ... và điều chỉnh mẫu cuối cùng phù hợp cho phù hợp.

Hoàn toàn khái quát hóa hàm này như một hàm trên các bộ dữ liệu tùy ý ity sẽ là có thể sử dụng HLists, nhưng đó rất có thể sẽ là một giải pháp nặng hơn rất nhiều so với cần thiết ở đây. Tôi sẽ để lại dòng này của cuộc tấn công như là một tập thể dục cho người hỏi (hoặc người bình luận khác ;-).

+0

Giải pháp rất đẹp! Cảm ơn bạn! –

+0

Là một bổ sung: Người ta phải nhận thức được thực tế là 'mapValues' trả về một khung nhìn. Xem câu trả lời hay của Rex Kerr ở đây: http://stackoverflow.com/questions/5433578/subsetof-versus-forall-contains –

1

tôi muốn đề nghị implicits trên tuples:

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) 
) 
Các vấn đề liên quan