如何将List中的相应值加总为元组?

时间:2014-01-10 10:30:24

标签: scala

我有这种类型的清单详情:

case class Detail(point: List[Double], cluster: Int)

val details = List(Detail(List(2.0, 10.0),1), Detail(List(2.0, 5.0),3),
                   Detail(List(8.0,  4.0),2), Detail(List(5.0, 8.0),2))

我希望将此列表过滤为一个元组,其中包含集群为2的每个对应点的总和

所以我过滤了这个列表:

details.filter(detail => detail.cluster == 2)

返回:

List(Detail(List(8.0, 4.0),2), Detail(List(5.0, 8.0),2))

这是我遇到麻烦的相应值的总和。在这个例子中,元组应该包含(8 + 5,4 + 8)=(13,12)

我正在考虑将List弄平,然后对每个相应的值求和,但

List(details).flatten 

只返回相同的List

如何将List中的相应值加总为元组?

我可以使用for循环轻松实现这一点,只需将我需要的细节提取到计数器中,但功能解决方案是什么?

2 个答案:

答案 0 :(得分:5)

如果不同Detail的列表长度不同,您希望发生什么? 或者相同的长度与2不同?元组通常仅在需要预先固定数量的元素时使用;如果你需要不同长度的元组,你甚至不能写一个返回类型。

假设所有这些都是相同长度的列表并且你得到一个列表作为回报,这样的东西应该可以工作(未经测试):

details.filter(_.cluster == 2).map(_.point).transpose.map(_.sum)

即。首先将所有point作为列表列表,将其转置,以便获得每个“坐标”的列表,并对每个列表求和。

如果您确实知道每个点都有两个坐标,那么这可能会反映在您的Point类型中,使用(Double, Double)而不是List[Double],您可以折叠列表积分,应该更有效率。根据{{​​1}}来看foldLeft的定义和sum的标准实现:

foldLeft

并且应该很容易做你想做的事。

答案 1 :(得分:0)

你可以只使用一个foldLeft和PF而不使用过滤器:

  details.foldLeft((0.0,0.0))({
    case ((accX, accY), Detail(x :: y :: Nil, 2)) => (accX + x, accY + y)
    case (acc, _) => acc
  })

  res1: (Double, Double) = (13.0,12.0)