архивирование списков с необязательным списком для создания списка объектов в Scala - PullRequest
1 голос
/ 07 апреля 2020

У меня есть такой класс дел:

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

Я получаю отдельные компоненты для построения метрик в отдельных списках и архивирую их для создания списка объектов Metri c.

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)
    }
}

Теперь мне нужно добавить необязательный параметр как для функции buildMetri c, так и для класса Metri c.

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]

Идея в том, что мы некоторые времена получают последовательность типа, которая, если присутствует, соответствует длине списков имен и значений. Я не уверен, как изменить тело функции buildMetri c для создания объектов Metri c с идиоматической информацией о типе. Я могу придумать пару подходов.

  1. Выполните if-else на types.isDefined, а затем заархивируйте типы с помощью types.get с другим списком в одном условии и оставьте, как указано выше, в другой. Это заставляет меня писать один и тот же код дважды.

  2. Другой вариант - просто использовать while l oop и создать объект Metri c, в котором types.map(_(i)) передан последний параметр .

Пока я использую второй вариант, но мне интересно, есть ли более функциональный способ решения этой проблемы.

Ответы [ 3 ]

3 голосов
/ 07 апреля 2020

Первый вариант невозможен, потому что 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)
  }
3 голосов
/ 07 апреля 2020

Еще один вариант с моей точки зрения, если вы хотите сохранить этот zipped подход - конвертируйте types из Option[Seq[Type]] в Seq[Option[Type]] с той же длиной, что и names, заполненная None значениями в если types равно None:

val optionTypes: Seq[Option[Type]] = types.fold(Seq.fill(names.length)(None: Option[Type]))(_.map(Some(_)))
// Sorry, Did not find `zipped` for Tuple4 case
names.zip(values).zip(ts).zip(optionTypes).toList.map {
  case (((name, value), time), optionType) => Metric(name, value, time, optionType)
}

Надеюсь, это поможет!

2 голосов
/ 07 апреля 2020

Вы можете просто использовать сопоставление с образцом на types:

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

  types match {
    case Some(types) => names.zip(values).zip(ts).zip(types).map {
        case (((name, value), ts,), t) => Metric(name, value, ts, Some(t))
    }
    case None => (names, values, ts).zipped.map(Metric(_, _, _, None))
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...