将列表映射拆分为映射列表的功能方法

puz*_*ent 5 ocaml haskell functional-programming scala

我有点卡在这个问题上.我觉得我在"倒退",这让我感到困惑.

我有一个Map[Long, Seq[String]]我想转换成一个Seq[Map[Long, String]].走向另一个方向相当简单,因为我们可以将元素组合在一起,但是,我不确定如何以功能方式将它们分开.

所以,

val x = Map(1 -> List("a","b","c"), 2 -> List("d", "e"), 3 -> List("f"))
Run Code Online (Sandbox Code Playgroud)

应该成为

List(Map(1 -> "a", 2 -> "d", 3 -> "f"), Map(1 -> "b", 2 -> "e"), Map(1 -> "c"))
Run Code Online (Sandbox Code Playgroud)

我正在考虑使用x.partition然后在每个结果元组上递归,但我不确定我要分区的内容:/

我正在用scala编写,但任何功能性答案都是受欢迎的(语言不可知).

chi*_*chi 5

在Haskell:

> import qualified Data.Map as M
> import Data.List
> m = M.fromList [(1,["a","b","c"]), (2,["d","e"]), (3,["f"])]
> map M.fromList . transpose . map (\(i,xs) -> map ((,) i) xs) . M.toList $ m
[fromList [(1,"a"),(2,"d"),(3,"f")],fromList [(1,"b"),(2,"e")],fromList [(1,"c")]]
Run Code Online (Sandbox Code Playgroud)

M.toListM.fromList地图转换为关联配对,和背部的列表.

map ((,) i) xs[(i,x) | x<-xs]添加(i,...)到每个元素相同.

transpose 与矩阵转置类似,在列表列表中交换"行"和"列".


Leo*_*o C 5

transpose从这个SO答案中借用一个简洁的方法,这是另一种方法:

def transpose[A](xs: List[List[A]]): List[List[A]] = xs.filter(_.nonEmpty) match {    
  case Nil =>  Nil
  case ys: List[List[A]] => ys.map{ _.head }::transpose(ys.map{ _.tail })
}

transpose[(Int, String)](
  x.toList.map{ case (k, v) => v.map( (k, _) ) }
).map{ _.toMap }

// Res1: List[scala.collection.immutable.Map[Int,String]] = List(
//   Map(1 -> a, 2 -> d, 3 -> f), Map(1 -> b, 2 -> e), Map(1 -> c)
// )
Run Code Online (Sandbox Code Playgroud)