2017-07-06 28 views
0

我有一個類如何使用Scala中的對象列表中的對象值創建求和變量?

class Test(val first: Int, val second: Int, val third: Int) 

類測試可以具有比第一其他屬性,第二和第三。

而且我有一個列表:

val list: List[Test] = List(new Test(0,1,2), new Test(1,14,2), new Test(7,15,2)) 

我將如何使用foldLeft此處添加所有first`s,第二我們一起,第三個是連同變量結束:

allFirsts = 8

allSeconds = 30

allThirds = 6

我已經有這樣的事情摸索出:

val (totalFirsts, totalSeconds, totalThirds) = list.foldLeft(0, 0, 0){ (sum, l) => (sum._1 + l.first , sum._2 + l.second, sum._3 + l.third) } 

這似乎很好地工作,但我不喜歡_1,_2,_3的可讀性。也許我可以在這裏使用case分解值,但我不確定如何使它們一起工作。

回答

0

你說得對,元組索引可能有點笨重。在這種情況下,您可以使用模式匹配。

val (totalFirsts, totalSeconds, totalThirds) = 
    list.foldLeft(0, 0, 0){case ((a,b,c), test) => 
    (a+test.first, b+test.second, c+test.third)} 

但是語法可以進一步簡化。如果你的Test類是case class,那麼它將有一個你可以在模式匹配中使用的提取器。

case class Test(first: Int, second: Int, third: Int) 
. . . 
val (totalFirsts, totalSeconds, totalThirds) = 
    list.foldLeft(0, 0, 0){case ((a,b,c), Test(f,s,t)) => (a+f, b+s, c+t)} 
1

可以定義另一種情況類來保存最初和最終的結果,那麼你可以使用first, second, third代替_1, _2, _3

case class Test1(val first: Int, val second: Int, val third: Int) 

list.foldLeft(Test1(0,0,0))((acc, t) => Test1(acc.first + t.first, acc.second + t.second, acc.third + t.third)) 
// res0: Test1 = Test1(8,30,6) 
+0

我會反對這個解決方案的唯一原因是因爲類Test可能具有除第一,第二和第三的其他屬性,我不想擔心實例化。 – NiceOneMoney

+0

case類不一定與'Test'類相同。定義另一個只有三個字段的案例類。 * Test1 *例如。 – Psidom

0

我不會使用它,但它的工作原理

case class Test3(a1: Int, a2: Int, a3: Int) 
    case class Test4(a1: Int, a2: Int, a3: Int, a4: Int) 

    import scala.reflect._ 
    def doMagic[T <: Product : ClassTag](data: List[T]): T ={ 
    val params: Seq[Object] = data.map(_.productIterator.toList.map(_.asInstanceOf[Int])) 
     .reduce((buffer, next) => buffer.zip(next).map { case (i, j) => i + j }).map(_.asInstanceOf[Object]) 
    classTag[T].runtimeClass.getConstructors()(0).newInstance(params:_*).asInstanceOf[T] 
    } 
    doMagic(List(Test3(1,2,3), Test3(2,3,4), Test3(10,20,30))) // Test3(13,25,37) 
    doMagic(List(Test4(1,2,3,5), Test4(2,3,4,0), Test4(10,20,30,100))) // Test4(13,25,37,105) 

待辦事項不要忘記使用reduceOption而不是reduce來處理空列表。這裏使用簡化代碼

相關問題