Конвертировать Seq [Option [Map [String, Any]]] в Option [Map [String, Any]] - PullRequest
0 голосов
/ 31 января 2020

Как конвертировать Seq[Option[Map[String, Any]]] в Option[Map[String, Any]]

Поэтому пропустите любой параметр, который отсутствует, и сохраните действительные Карты и объедините их. Если для каждого параметра выбрано None, то и последним также должно быть None.

Ответы [ 3 ]

1 голос
/ 31 января 2020

A flatMap вместе с groupMapReduce, за которым следует опция filter, должна выполнить работу:

val listOfMaps: List[Option[Map[String, Any]]] =
  List(Some(Map("a"->"p", "b"->2)), None, Some(Map("a"->"q", "c"->"r")))

val mergedMap = listOfMaps.
  flatMap(_.getOrElse(Map.empty[String, Any])).
  groupMapReduce(_._1)(t => List[Any](t._2))(_ ::: _)
// mergedMap: Map[String, List[Any]] = 
//   Map("a" -> List("p", "q"), "b" -> List(2), "c" -> List("r"))

Option(mergedMap).filter(_.nonEmpty)
// res1: Option[Map[String, List[Any]]] =
//   Some(Map("a" -> List("p", "q"), "b" -> List(2), "c" -> List("r")))

Несколько примечаний:

  1. groupMapReduce доступно только для Scala 2.13 +.

  2. Если вам нужно придерживаться Seq вместо List, просто замените метод ::: с ++ в groupMapReduce.

  3. Предполагается, что объединение карт означает объединение значений карты общего ключа в список. Замените groupMapReduce на toMap, если вместо этого требуется оставить только одно из значений Map общего ключа.

  4. В этом решении Some(Map(.empty[String, Any])) аналогично None.

0 голосов
/ 01 февраля 2020

Вот пример с flatten, fold, ++ и совпадением в конце для обеспечения Some или None.

баз. scala

package baz
object baz {
  // fixtures
  val x0 = Seq[Option[Map[String, Any]]]()
  val x1 = Seq[Option[Map[String, Any]]](None)
  val x2 = Seq[Option[Map[String, Any]]](Some(Map("a" -> 1, "b" -> "two")))
  val x3 = Seq[Option[Map[String, Any]]](Some(Map("a" -> 1, "b" -> "two")), Some(Map("c" -> 3.0)), None)

  def f(x: Seq[Option[Map[String, Any]]]) =
    x.flatten.fold(Map[String, Any]())((a,b) => a ++ b) match { case m if m.isEmpty => None case m => Some(m) }
}

Пробный прогон

bash-3.2$ scalac baz.scala && scala -classpath .
Welcome to Scala 2.13.1 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_66).
Type in expressions for evaluation. Or try :help.

scala> import baz.baz._
import baz.baz._

scala> x0 -> f(x0)
res0: (Seq[Option[Map[String,Any]]], Option[Map[String,Any]]) = (List(),None)

scala> x1 -> f(x1)
res1: (Seq[Option[Map[String,Any]]], Option[Map[String,Any]]) = (List(None),None)

scala> x2 -> f(x2)
res2: (Seq[Option[Map[String,Any]]], Option[Map[String,Any]]) = (List(Some(Map(a -> 1, b -> two))),Some(Map(a -> 1, b -> two)))

scala> x3 -> f(x3)
res3: (Seq[Option[Map[String,Any]]], Option[Map[String,Any]]) = (List(Some(Map(a -> 1, b -> two)), Some(Map(c -> 3.0)), None),Some(Map(a -> 1, b -> two, c -> 3.0)))

scala> :quit
0 голосов
/ 31 января 2020

Это однострочное решение

val in: Seq[Option[Map[String, Any]]] = ???

val out: Option[Map[String, Any]] =
  in.flatten.headOption.map(_ => in.flatten.reduce(_ ++ _))

in.flatten.headOption - это простой способ получить Some, если хотя бы один из элементов равен Some или None, если они all None.

reduce просто объединяет все Map s в один.

Это можно легко оптимизировать, избегая дублирования вызова in.flatten.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...