我有这种类型的清单详情:
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循环轻松实现这一点,只需将我需要的细节提取到计数器中,但功能解决方案是什么?
答案 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)