我想根据内部列表中元素的值合并List[List[Double]]
。这是我到目前为止所做的:
// inner Lists are (timestamp, ID, measurement)
val data = List(List(60, 0, 3.4), List(60, 1, 2.5), List(120, 0, 1.1),
List(180, 0, 5.6), List(180, 1, 4.4), List(180, 2, 6.7))
data
.foldLeft(List[List[Double]]())(
(ret, ll) =>
// if this is the first list, just add it to the return val
if (ret.isEmpty){
List(ll)
// if the timestamps match, add a new (ID, measurement) pair to this inner list
} else if (ret(0)(0) == ll(0)){
{{ret(0) :+ ll(1)} :+ ll(2)} :: ret.drop(1)
// if this is a new timestamp, add it to the beginning of the return val
} else {
ll :: ret
}
)
这很有效,但它对我来说并不是最佳的(特别是正确的加法“:+
”)。对于我的用例,我有一个非常大的(~25,000个内部列表)元素列表,它们本身都是长度为3的列表。最多会有四倍的简并性,因为内部列表是List(timestamp, ID, measurement)
组,并且只有四个唯一ID。基本上,我想将所有具有相同时间戳的测量结果汇总在一起。
有没有人看到更好的方法呢?
如果从这一点开始有更好的方法,我实际上从四个ID中的每一个开始都有List[Double]
个时间戳和List[Double]
个测量值。
答案 0 :(得分:2)
这是一种稍微简短的方法:
data.
groupBy(_(0)).
mapValues(_.flatMap(_.tail)).
toList.
map(kv => kv._1 :: kv._2)
结果看起来与您的算法产生的结果完全相同:
List(List(180.0, 0.0, 5.6, 1.0, 4.4, 2.0, 6.7), List(120.0, 0.0, 1.1), List(60.0, 0.0, 3.4, 1.0, 2.5))
List(List(180.0, 0.0, 5.6, 1.0, 4.4, 2.0, 6.7), List(120.0, 0.0, 1.1), List(60.0, 0.0, 3.4, 1.0, 2.5))
说明:
答案 1 :(得分:2)
这是一种可能性:
input
.groupBy(_(0))
.map { case (tstp, values) => tstp :: values.flatMap(_.tail) }
这个想法只是按照第一个元素对内部列表进行分组,然后将结果值展平。
返回:
List(List(180.0, 0.0, 5.6, 1.0, 4.4, 2.0, 6.7), List(120.0, 0.0, 1.1), List(60.0, 0.0, 3.4, 1.0, 2.5))
答案 2 :(得分:1)
如何用案例类来表示您的测量结果?
case class Measurement(timestamp: Int, id: Int, value: Double)
val measurementData = List(Measurement(60, 0, 3.4), Measurement(60, 1, 2.5),
Measurement(120, 0, 1.1), Measurement(180, 0, 5.6),
Measurement(180, 1, 4.4), Measurement(180, 2, 6.7))
measurementData.foldLeft(List[Measurement]())({
case (Nil, m) => List(m)
case (x :: xs, m) if x.timestamp == m.timestamp => m :: xs
case (xs, m) => m :: xs
})