首页 > 解决方案 > Scala - 如何过滤嵌套的集合结构?

问题描述

这是我的案例课程:

case class Metric (
id: Long,
name: String,
features: List[Feature]
)

case class Feature (
featureId: Long,
name: String,
value: String,
processTime: Timestamp
)

每个指标都有一个List[Feature]. 我想过滤每个指标,使其List[Feature]仅包含每个featureId.

我尝试了以下方法,但它返回了List[immutable.Iterable[Feature]]正确过滤功能的地方。但是我需要它来重新使用List[Metric]其中的过滤功能列表。

val f1 = Feature(1, "f1", "v1", Timestamp.valueOf("2019-07-01 00:00:00"))
val f2 = Feature(1, "f2", "v2", Timestamp.valueOf("2019-07-05 00:00:00"))
val f3 = Feature(2, "f3", "v3", Timestamp.valueOf("2019-03-07 00:00:00"))
val f4 = Feature(2, "f4", "v4", Timestamp.valueOf("2019-03-10 00:00:00"))

val metric1 = Metric(1, "m1", List(f1, f2, f3, f4))
val metric2 = Metric(1, "m1", List(f3, f4))

val metricsList = List(metric1, metric2)

val newMetrics = metricsList.map(m => m.features.groupBy(_.featureId)
  .map { case (featureId, metricsList) => metricsList.reduce {
    (m1: Feature, m2: Feature) => if (m1.processTime.after(m2.processTime)) m1 else m2
  }
  })

UPD:预期输出是List(metric1, metric2)where

val metric1 = Metric(1, "m1", List(f2,f4))val metric2 = Metric(1, "m1", List(f4))

标签: scalacollections

解决方案


您可以在您的班级上使用案例类copy方法来执行此操作Metric。这将创建一个Metric具有过滤功能的新实例。请注意,您也可以使用maxBy,因此您不需要使用reduce. 为此,您需要提供一个Ordering隐式来对时间戳进行排序。下面的代码应该做你正在寻找的:

implicit def ordered: Ordering[Timestamp] = new Ordering[Timestamp] {
  def compare(x: Timestamp, y: Timestamp): Int = x compareTo y
}

val newMetrics = metricsList.map(m => {
  val features = m.features.groupBy(_.featureId).mapValues(_.maxBy(_.processTime)).values
  m.copy(features = features.toList)
})

推荐阅读