2017-04-21 1 views
1

각 과일의 수를 유형에 따라 확인하고 싶습니다. 분명히 나는 ​​그들을 어떤 방법으로 축적해야하지만 무엇이 가장 깨끗하고/깨끗한가? 당신은 패턴 일치로 count을 사용할 수 있습니다목록의 요소를 스칼라의 유형에 따라 계산하십시오.

trait Fruit 
case object Apple extends Fruit 
case object Pear extends Fruit 
case class Orange(variety: String) extends Fruit 

val fruits = List(Pear, Apple, Pear, Pear, Apple, Orange("satsuma"), Orange("clementine")) 

val numberOfOranges = ??? 
val numberOfApples = ??? 
val numberOfPears = ??? 

감사

답변

4

당신은 패턴 매칭으로 groupBy을 사용할 수 있습니다 .

+0

나는이 솔루션이 마음에 들지만 그렇지는 않을 것 같다. val counts = fruits.groupBy { case _ : T => T } .map { case (key, values) => (key, values) => .size) } –

+0

아니요, 작동하지 않습니다. 추상적 인 유형에는 패턴 일치를 사용할 수 없습니다. 당신은 아마 반사와 함께 뭔가를 할 수 있습니다. –

2

이 작업을 수행합니다 :

val numberOfOranges = fruits.count { case Orange(_) => true 
            case _ => false } 

위의 2. 그냥 다른 예에 대한 패턴 일치를 변경 인쇄됩니다. (당신이 문자열을 원하는 경우, 또는 getClass.getSimpleName) 당신이 fruits.groupBy(_.getClass)을 사용할 수 있습니다, 당신은 반사를 좋아하는 경우에

val counts = fruits.groupBy{ 
    case Apple => "apple" 
    case Pear => "pear" 
    case Orange(_) => "orange" 
}.map{ 
    case (key, values) => (key, values.size) 
} 

편집을하고 하위 유형 유형의 매개 변수가 없습니다 :

+0

가능한 경우 목록을 반복하는 것이 좋습니다. –

1

당신은 당신의 groupBygetClass을 사용할 수 있습니다 : 당신이 범위의 형식을 가지고 패턴 일치를 사용할 필요가 있지만

fruits.groupBy(f => f.getClass.getSimpleName).mapValues(_.size) 

// result: Map(Apple$ -> 2, Pear$ -> 3, Orange -> 2) 
+0

나는 이것을 좋아하지만 달러 표시는 수치 스럽다 :-) –

+0

은'mapValues'가 게으 르기 때문에 요청할 때마다 각 목록의 크기를 다시 계산할 것이다. –

2

여기, 반사를 사용하여 솔루션입니다. 목록을 일반적으로 반복 할 수없고 각 요소의 유형을 가져올 수 없습니다.

val orangeType = reflect.runtime.universe.typeOf[Orange] 
val appleType = reflect.runtime.universe.typeOf[Apple.type] 
val pearType = reflect.runtime.universe.typeOf[Pear.type] 

def getType[T: reflect.runtime.universe.TypeTag](obj: T) = 
    reflect.runtime.universe.typeOf[T] 

def typesOf[A](fs: List[A]): List[reflect.runtime.universe.Type] = { 
    fs.map { 
    // Use pattern match to reify type 
    case v @ Apple => getType(v) 
    case v @ Pear => getType(v) 
    case v @ Orange(_) => getType(v) 
    } 
} 

val fruitCount = typesOf(fruits).groupBy(identity).mapValues(_.size) 

val numberOfOranges = fruitCount(orangeType) 
val numberOfApples = fruitCount(appleType) 
val numberOfPears = fruitCount(pearType) 

솔직히, 이것은 단지 스칼라 반사 유형보다는 빨리 이상의 문자열과 같은 명백한 (또는 다른 원시 형)과 무언가에 의해 그룹화되어 지나치게 복잡해진다. 가장 좋은 장기 코딩 솔루션은 여러분이 직접 열거하고 IMO를 사용하는 것입니다.

관련 문제