How do I transform a List[String] to a List[Map[String,String]] given that the list of string represents the keys to the map in Scala?

Viewed 99

I have a list of references:

val references: List[String]= List("S","R")

I also have variables which is:

val variables: Map[String,List[String]]=("S"->("a","b"),"R"->("west","east"))

references is a list of keys of the variables map.

I want to construct a function which takes:

def expandReplacements(references:List[String],variables:Map[String,List[String]]):List[Map(String,String)]

and this function should basically create return the following combinations

List(Map("S"->"a"),("R"->"west"),Map("S"->"a"),("R"->"east"),Map("S"->"b"),("R"->"west"),Map("S"->"b"),("R"->"east"))

I tried doing this:

val variables: Map[String,List[String]] = Map("S" -> List("a", "b"), "R" -> List("east", "central"))
val references: List[String] = List("S","R")

def expandReplacements(references: List[String]): List[Map[String, String]] =
  references match {
    case ref :: refs =>
      val variableValues =
        variables(ref)
      val x = variableValues.flatMap { variableValue =>
        val remaining = expandReplacements(refs)
        remaining.map(rem => rem + (ref -> variableValue))
      }
      x

    case Nil => List.empty
  }
3 Answers

If you have more than 2 references, you can do:

def expandReplacements(references: List[String], variables :Map[String,List[String]]): List[Map[String, String]] = {
  references match {
    case Nil => List(Map.empty[String, String])
    case x :: xs =>
      variables.get(x).fold {
        expandReplacements(xs, variables)
      } { variableList =>
        for {
          variable <- variableList.map(x -> _)
          otherReplacements <- expandReplacements(xs, variables)
        } yield otherReplacements + variable
      }
  }
}

Code run at Scastie.

So I have Figured it Out

def expandSubstitutions(references: List[String]): List[Map[String, String]] =
        references match {
          case r :: Nil => variables(r).map(v => Map(r -> v))
          case r :: rs  => variables(r).flatMap(v => expandSubstitutions(rs).map(expanded => expanded + (r -> v)))
          case Nil      => Nil
        }

This Returns:

List(Map(R -> west, S -> a), Map(R -> east, S -> a), Map(R -> west, S -> b), Map(R -> east, S -> b))

Your references representation is suboptimal but if you want to use it...

val variables: Map[String,List[String]] = [S -> List("a", "b"), R -> List("east", "central")]
val references: List[String] = List("S","R")

def expandReplacements(references: List[String]): List[Map[String, String]] =
  references match {
    case List(aKey, bKey) =>
      val as = variables.get(aKey).toList.flatten
      val bs = variables.get(bKey).toList.flatten

      as.zip(bs).map { case (a, b) =>
        Map(aKey -> a, bKey -> b)
      }
    case _ => Nil
  }
Related