首页 > 解决方案 > 使用可选列表压缩列表以在 Scala 中构造对象列表

问题描述

我有一个这样的案例类:

case class Metric(name: String, value: Double, timeStamp: Int)

我收到单独的组件以在单独的列表中构建指标并将它们压缩以创建指标对象列表。

def buildMetric(names: Seq[String], values: Seq[Double], ts: Seq[Int]): Seq[Metric] = {
    (names, values, ts).zipped.toList map {
         case (name, value, time) => Metric(name, value, time)
    }
}

现在我需要为 buildMetric 函数和 Metric 类添加一个可选参数。

case class Metric(name: String, value: Double, timeStamp: Int, type: Option[Type])

&

def buildMetric(names: Seq[String], values: Seq[Double], ts: Seq[Int], types: Option[Seq[Type]]): Seq[Metric]

这个想法是我们有时会收到一个类型的序列,如果存在的话,它与名称和值列表的长度相匹配。我不确定如何修改 buildMetric 函数的主体以惯用地创建具有类型信息的 Metric 对象。我可以想到几种方法。

  1. 执行 if-else on types.isDefined,然后types.get在一种情况下使用另一个列表压缩类型,并在另一种情况下如上所示。这使我两次编写相同的代码。

  2. 另一种选择是简单地使用 while 循环并创建一个types.map(_(i))传递最后一个参数的 Metric 对象。

到目前为止,我使用的是第二个选项,但我想知道是否有更实用的方法来处理这个问题。

标签: scalafunctional-programming

解决方案


第一个选项无法完成,因为zipped仅适用于 3 个或更少元素的元组。第二个版本可能如下所示:

def buildMetric(names: Seq[String], values: Seq[Double], ts: Seq[Int], types: Option[Seq[Type]]): Seq[Metric] =
  for {
    (name, i) <- names.zipWithIndex
    value <- values.lift(i)
    time <- ts.lift(i)
    optType = types.flatMap(_.lift(i))
  } yield {
    Metric(name, value, time, optType)
  }

推荐阅读