1
votes

zipper des listes avec une liste facultative pour construire une liste d'objets dans Scala

J'ai une classe de cas comme celle-ci:

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

Je reçois des composants individuels pour créer des métriques dans des listes séparées et les compresser pour créer une liste d'objets métriques.

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

Je dois maintenant ajouter un paramètre facultatif à la fois à la fonction buildMetric et à la classe Metric.

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

&

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


0 commentaires

3 Réponses :


3
votes

Une autre option de mon point de vue, si vous souhaitez conserver cette approche zippée - convertir les types depuis Option [Seq [Type]] à Seq [Option [Type]] avec la même longueur que les noms remplis avec des valeurs Aucun dans le cas où types code> est également Aucun :

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

J'espère que cela vous aidera!


1 commentaires

Merci, j'ai essayé ça. C'est une bonne approche mais j'ai été surpris de voir que l'opération Seq.fill semble très intensive en CPU. Lors du test, l'utilisation du processeur dans mon cluster est passée de 4-5% à 50-70%!



3
votes

La première option ne peut pas être effectuée car zipped ne fonctionne qu'avec des tuples de 3 éléments ou moins. La deuxième version pourrait ressembler à ceci:

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


0 commentaires

2
votes

Vous pouvez simplement utiliser la correspondance de motifs sur les 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))
  }
}


0 commentaires