2017-04-21 47 views
1

我想根據它們的類型獲取每個水果的編號。顯然我需要以某種方式積累它們,但最好的/最乾淨的/ etc是什麼?根據Scala的類型來計算列表的元素

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與模式匹配:

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

編輯如果你喜歡思考,你的亞型沒有類型的參數,你可以使用fruits.groupBy(_.getClass)(或getClass.getSimpleName,如果你想字符串) 。

+0

我喜歡這個解決方案,但是不是,這是可能的: val counts = fruits.groupBy case_:T => T } .map { case(key,values)=>(key,values, .size) } –

+0

不,那不行。您無法對抽象類型進行模式匹配。儘管如此,你或許可以用反射來做些事情。 –

2

可以使用count與模式匹配來做到這一點:

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

上面會打印2.只要改變模式匹配您的其他例子。

+0

如果可能,我寧願只迭代一次列表。 –

1

您可以在groupBy使用getClass

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。