Разверните Map[String,List[String]] в декартово произведение в Scala

Я ищу версию Расширить набор[ Установите [String]] в декартово произведение в Scala в зависимости от типа карты:

Я хотел бы начать с:

val values = Map(
      "id" -> List("Paul","Joe"),
      "number" -> List("1","2","3"),
      "Type" -> List("A","B","C")
    )

И вычислить:

val final = Set(
Map("id" -> "Paul", "number" -> "1", "Type" -> "A" ),
Map("id" -> "Paul", "number" -> "1", "Type" -> "B" ),
Map("id" -> "Paul", "number" -> "1", "Type" -> "C" ),
Map("id" -> "Paul", "number" -> "1", "Type" -> "A" ),
Map("id" -> "Paul", "number" -> "1", "Type" -> "B" ),
Map("id" -> "Paul", "number" -> "1", "Type" -> "C" ),
Map("id" -> "Paul", "number" -> "2", "Type" -> "A" ),
Map("id" -> "Paul", "number" -> "2", "Type" -> "B" ),
Map("id" -> "Paul", "number" -> "2", "Type" -> "C" ),
....
Map("id" -> "Joe", "number" -> "3", "Type" -> "B" ),
Map("id" -> "Joe", "number" -> "3", "Type" -> "C" )
)

Я пытаюсь преобразовать следующий код

def combine[A](xs: Traversable[Traversable[A]]): Seq[Seq[A]] =
     xs.foldLeft(Seq(Seq.empty[A])){
     (x, y) => for (a <- x.view; b <- y) yield a :+ b }

но у меня есть некоторая проблема, чтобы понять, как построить всю карту, чтобы добавить ее в большой Set()


person Wilson Wii    schedule 29.03.2021    source источник


Ответы (1)


Вы можете сделать что-то вроде этого:
(но обратите внимание, что для больших карт это потребует много памяти, возможно, стоит вместо этого создать LazyList)

def cartesianProductMap[A, B](data: Map[A, List[B]]): List[Map[A, B]] =
  data.foldLeft(Map.empty[A, B] :: Nil) {
    case (acc, (key, values)) =>
      values.flatMap { b =>
        acc.map(_ + (key -> b))
      }
  }

Код выполняется в Scastie.


Кстати, если вы используете кошки, вы можете просто сделать: values.to(SortedMap).sequence

person Luis Miguel Mejía Suárez    schedule 29.03.2021