2017-07-06 77 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来处理空列表。这里使用简化代码

相关问题