, 내가 Manifest
를 사용하여 더 나은 방법이 확신하지만, 패턴 매칭이 Seq
및 Map
을 구별하는 것 같다 그래서 여기있다 :
object Foo {
def mapValues[A <: Map[_, _], C, D](map: A)(f: C => D): Map[_, _] = map.mapValues {
case seq: Seq[C] => seq.groupBy(f)
case innerMap: Map[_, _] => mapValues(innerMap)(f)
}
}
scala> val group0 = List("fooo", "bar", "foo") groupBy (_(0))
group0: scala.collection.immutable.Map[Char,List[java.lang.String]] = Map((f,List(fooo, foo)), (b,List(bar)))
scala> val group1 = Foo.mapValues(group0)((x: String) => x(1))
group1: scala.collection.immutable.Map[_, Any] = Map((f,Map(o -> List(fooo, foo))), (b,Map(a -> List(bar))))
scala> val group2 = Foo.mapValues(group1)((x: String) => x(2))
group2: scala.collection.immutable.Map[_, Any] = Map((f,Map(o -> Map(o -> List(fooo, foo)))), (b,Map(a -> Map(r -> List(bar)))))
편집 : 여기가 높 사용하여 입력 된 버전입니다 kinded 유형.
trait NestedMapValue[Z] {
type Next[X] <: NestedMapValue[Z]
def nextValues[D](f: Z => D): Next[D]
}
trait NestedMap[Z, A, B <: NestedMapValue[Z]] extends NestedMapValue[Z] { self =>
type Next[D] = NestedMap[Z, A, B#Next[D]]
val map: Map[A, B]
def nextValues[D](f: Z => D): Next[D] = self.mapValues(f)
def mapValues[D](f: Z => D): NestedMap[Z, A, B#Next[D]] = new NestedMap[Z, A, B#Next[D]] { val map = self.map.mapValues {
case x: B => x.nextValues[D](f)
}}
override def toString = "NestedMap(%s)" format (map.toString)
}
trait Bottom[A] extends NestedMapValue[A] {
type Next[D] = NestedMap[A, D, Bottom[A]]
val seq: Seq[A]
def nextValues[D](f: A => D): Next[D] = seq match {
case seq: Seq[A] => groupBy[D](f)
}
def groupBy[D](f: A => D): Next[D] = seq match {
case seq: Seq[A] =>
new NestedMap[A, D, Bottom[A]] { val map = seq.groupBy(f).map { case (key, value) => (key, new Bottom[A] { val seq = value })} }
}
override def toString = "Bottom(%s)" format (seq.toString)
}
object Bottom {
def apply[A](aSeq: Seq[A]) = new Bottom[A] { val seq = aSeq }
}
scala> val group0 = Bottom(List("fooo", "bar", "foo")).groupBy(x => x(0))
group0: NestedMap[java.lang.String,Char,Bottom[java.lang.String]] = NestedMap(Map(f -> Bottom(List(fooo, foo)), b -> Bottom(List(bar))))
scala> val group1 = group0.mapValues(x => x(1))
group1: NestedMap[java.lang.String,Char,Bottom[java.lang.String]#Next[Char]] = NestedMap(Map(f -> NestedMap(Map(o -> Bottom(List(fooo, foo)))), b -> NestedMap(Map(a -> Bottom(List(bar))))))
scala> val group2 = group1.mapValues(x => x.size)
group2: NestedMap[java.lang.String,Char,Bottom[java.lang.String]#Next[Char]#Next[Int]] = NestedMap(Map(f -> NestedMap(Map(o -> NestedMap(Map(4 -> Bottom(List(fooo)), 3 -> Bottom(List(foo)))))), b -> NestedMap(Map(a -> NestedMap(Map(3 -> Bottom(List(bar))))))))
마지막 문장은 매우 사실입니다. 나는 당신의 해결책과 유진으로 놀기 시작했다. 유진과 함께 빠른 결과를 얻었습니다. 이 과정에서 나는 런타임 캐스팅 예외 (내 오류가 있지만 컴파일러가 그것을 잡았 으면 좋겠다)를 가로 질러 실행했다. 그래서 형 안전함을 시험해 볼 것이라고 생각했습니다. 불행히도, 나는 암묵적으로 발견 된 오류를 겪고 있습니다. 내가 알아낼 수 없다면 나는 내 컴퓨터로 돌아와서 요점을 게시 할 것이다. – huynhjl
좋아, 내가 암시 적으로 범위에 가져 오려고했지만 실패했다. 이것은 귀하의 코드 https://gist.github.com/950580을 사용한 방법입니다. 나는 방법을 사용하는 범위에서 함축을 정의해야했습니다. 처음에는 CanMapInner 동반자 개체에 넣고 가져 오려고했으나 작동하지 않았습니다. – huynhjl