복붙노트

[SCALA] 일반적인 방법에서 원래 수집 유형을 반환

SCALA

일반적인 방법에서 원래 수집 유형을 반환

우리가 수집 동일 미니멀리즘의 모든 요소를 ​​반환 minBy 같은 기능을하고 싶은 말 :

def multiMinBy[A, B: Ordering](xs: Traversable[A])(f: A => B) = {
  val minVal = f(xs minBy f)
  xs filter (f(_) == minVal)
}

scala> multiMinBy(List("zza","zzza","zzb","zzzb"))(_.last)
res33: Traversable[java.lang.String] = List(zza, zzza)

지금까지 좋은, 그래서 우리는에 이동 다시 대신 우리의 초기 목록을 가지고 것을 제외하고.

난에 서명을 변경 시도 그래서

def multiMinBy[A, B: Ordering, C <: Traversable[A]](xs: C)(f: A => B)

희망 나는에 이동 [A]가 아니라 다시 C를 얻을 수 있습니다. 그러나, 나는 아무것도 다시 얻지 않는다 :

scala> multiMinBy(List("zza","zzza","zzb","zzzb"))(_.last)

<console>:9: error: inferred type arguments [Nothing,Nothing,List[java.lang.String]] 
do not conform to method multiMinBy's type parameter bounds [A,B,C <: Traversable[A]]

나는 A가 추정되기 전에 우리는 C가 인수에 나타나는 때문에이 생각? 나는 인수의 순서를 뒤집어 및 캐스트를 추가 그래서 :

def multiMinBy[A, B: Ordering, C <: Traversable[A]](f: A => B)(xs: C) = {
  val minVal = f(xs minBy f)
  (xs filter (f(_) == minVal)).asInstanceOf[C]
}

우리는 다음과 같이 호출 할 필요가 제외되는 작동 :

multiMinBy((x: String) => x.last)(List("zza","zzza","zzb","zzzb"))

올바른 수집 유형 등을 가져 오는 동안, 원래의 구문을 유지하는 방법이 있나요?

해결법

  1. ==============================

    1.나는 마일 사빈 솔루션은 너무 복잡하다 생각합니다. 스칼라의 수집은 이미 아주 작은 변화와 함께 작동하도록하는 데 필요한 기계를 가지고 :

    나는 마일 사빈 솔루션은 너무 복잡하다 생각합니다. 스칼라의 수집은 이미 아주 작은 변화와 함께 작동하도록하는 데 필요한 기계를 가지고 :

    import scala.collection.TraversableLike
    def multiMinBy[A, B: Ordering, C <: Traversable[A]]
                  (xs: C with TraversableLike[A, C])
                  (f: A => B): C = {
      val minVal = f(xs minBy f)
      xs filter (f(_) == minVal)
    }
    
  2. ==============================

    2.어떻게 CanBuildFrom 사용에 대한?

    어떻게 CanBuildFrom 사용에 대한?

    import scala.collection.immutable._
    import scala.collection.generic._
    
    def multiMinBy[A, B, From[X] <: Traversable[X], To](xs: From[A])(f: A => B)
      (implicit ord: Ordering[B], bf: CanBuildFrom[From[_], A, To])  = {
      val minVal = f(xs minBy f)
      val b = bf()
      b ++= (xs filter (f(_) == minVal))
      b.result
    } 
    
    
    
    scala> multiMinBy(List("zza","zzza","zzb","zzzb"))(_.last)
    res1: List[java.lang.String] = List(zza, zzza)
    
  3. ==============================

    3.귀하의 문제는 GenTraversable [A]에하는 방법으로 볼 때 필터 메소드의 결과 유형이 GenTraversable [A]보다 더 정확한 없다 (나는이 대답에 이동 [A] 대신 사용할 것이다하는) 것입니다. 불행하게도 multiMinBy 방법의 신체 내에서 그건 당신이 XS에 대해 알고 전부 기록한다.

    귀하의 문제는 GenTraversable [A]에하는 방법으로 볼 때 필터 메소드의 결과 유형이 GenTraversable [A]보다 더 정확한 없다 (나는이 대답에 이동 [A] 대신 사용할 것이다하는) 것입니다. 불행하게도 multiMinBy 방법의 신체 내에서 그건 당신이 XS에 대해 알고 전부 기록한다.

    당신이 multiMinBy의 서명이 더 정확한 수 있도록해야합니다 후있어 결과를 얻으려면. 여전히 상대적으로 개방 컨테이너 유형을 떠나는 동안이 일을 한 가지 방법은 다음과 같은 구조 유형을 사용하는 것입니다,

    type HomFilter[CC[X] <: GenTraversable[X], A] = 
      CC[A] { def filter(p : A => Boolean) : CC[A] }
    
    def multiMinBy[CC[X] <: GenTraversable[X], A, B: Ordering]
      (xs: HomFilter[CC, A])(f: A => B) : CC[A] = {
        val minVal = f(xs minBy f)
        xs filter (f(_) == minVal)
      }
    

    구조적 타입 HomFilter은 우리가 multiMinBy의 인수가 원하는 결과 유형 필터 방법이 있어야합니다 주장 할 수 있습니다.

    샘플 REPL 세션,

    scala> val mmb = multiMinBy(List("zza","zzza","zzb","zzzb"))(_.last)
    mmb: List[String] = List(zza, zzza)
    

    마음에 곰이 컨테이너 단지에 이동하는 것이보다 엄격한 요구 사항입니다 : GenTraversable의 아형이 방법으로 정기적으로하지 필터 방법을 정의하는 것이 허용합니다. 정적에서 같은 유형의 값을 방지 할 수 위의 서명 후 당신 행동이 있다는 아마도 ... multiMinBy에 전달된다.

  4. from https://stackoverflow.com/questions/8235462/returning-original-collection-type-in-generic-method by cc-by-sa and MIT license