我可以在Scala中压缩两个以上的列表吗?

鉴于以下Scala列表:

val l = List(List("a1", "b1", "c1"), List("a2", "b2", "c2"), List("a3", "b3", "c3")) 

我怎样才能得到:

 List(("a1", "a2", "a3"), ("b1", "b2", "b3"), ("c1", "c2", "c3")) 

由于zip只能用来组合两个列表,我认为你需要以某种方式迭代/减less主列表。 毫不奇怪,以下是不起作用的:

 scala> l reduceLeft ((a, b) => a zip b) <console>:6: error: type mismatch; found : List[(String, String)] required: List[String] l reduceLeft ((a, b) => a zip b) 

任何build议一个如何做到这一点? 我想我错过了一个非常简单的方法来做到这一点。

更新:我正在寻找一个解决scheme,可以采取每个M元素的N列表列表,并创build一个M TupleNs列表。

更新2:事实certificate,我的具体用例有一个列表列表,而不是一个元组列表,所以我接受南瓜的回应。 这也是最简单的,因为它使用本地方法。

我不相信有可能生成任意大小的元组列表,但是如果您不介意获取列表的列表, 转置函数完全可以满足您的需求。

 scala> (List(1,2,3),List(4,5,6),List(7,8,9)).zipped.toList res0: List[(Int, Int, Int)] = List((1,4,7), (2,5,8), (3,6,9)) 

备查。

所以这段代码不会回答OP的需求,不仅因为这是一个四岁的线程,而且它确实回答了题目问题,也许有人甚至会觉得它有用。

要压缩3个集合:

 as zip bs zip cs map { case ((a,b), c) => (a,b,c) } 

是的,用zip3 。

Scala将所有不同的元组大小视为不同的类( Tuple1Tuple2Tuple3Tuple4 ,…, Tuple22 ),尽pipe它们都是从Product traitinheritance而来的,但是这个trait没有足够的信息来实际使用数据值从不同大小的元组,如果他们都可以通过相同的函数返回。 (而斯卡拉的generics也不足以处理这种情况。)

你最好的select是为所有22个元组大小写入zip函数的重载。 代码生成器可能会帮助你。

我不相信这是可能的,而不是重复。 出于一个简单的原因:你不能定义你所要求的函数的返回types。

例如,如果你的input是List(List(1,2),List(3,4)),那么返回types是List [Tuple2 [Int]]。 如果它有三个元素,返回types将是List [Tuple3 [Int]],依此类推。

你可以返回列表[AnyRef],甚至列表[产品],然后做一堆的情况下,每个条件。

至于一般的List转置,这个工作:

 def transpose[T](l: List[List[T]]): List[List[T]] = l match { case Nil => Nil case Nil :: _ => Nil case _ => (l map (_.head)) :: transpose(l map (_.tail)) } 

transpose做的伎俩。 一个可能的algorithm是:

 def combineLists[A](ss:List[A]*) = (ss.head.map(List(_)) /: ss.tail)(_.zip(_).map(p=>p._2 :: p._1)) 

例如:

 combineLists(List(1, 2, 3), List(10,20), List(100, 200, 300)) // => List[List[Int]] = List(List(100, 10, 1), List(200, 20, 2)) 

答案被截断为input中最短列表的大小。

 combineLists(List(1, 2, 3), List(10,20)) // => List[List[Int]] = List(List(10, 1), List(20, 2)) 

如果你不想在应用程序scalaz / cats /(在这里插入你喜欢的函数库)path,模式匹配是要走的路,尽pipe(_, _)语法在嵌套时有点不方便,所以让我们更改:

 import scala.{Tuple2 => &} for (i1 & i2 & i3 & i4 <- list1 zip list2 zip list3 zip list4) yield (i1, i2, i3, i4) 

&在这里是一个随意的select,任何看起来不错的中缀应该这样做。 不过,在代码审查期间,您可能会收到一些提高的眉毛。

它也应该与任何你可以zip (如Future

产品集合有一个flatZip操作直到22。

 scala> List(1,2,3) flatZip Seq("a","b","c") flatZip Vector(1.0,2.0,3.0) flatZip Seq(9,8,7) res1: com.github.marklister.collections.immutable.CollSeq4[Int,String,Double,Int] = CollSeq((1,a,1.0,9), (2,b,2.0,8), (3,c,3.0,7)) 

随着斯卡拉:

 import scalaz.Zip import scalaz.std.list._ // Zip 3 Zip[List].ap.tuple3(List("a1", "b1"), List("a2", "b2"), List("a3", "b3")) // Zip 4 Zip[List].ap.tuple4(List("a1", "b1"), List("a2", "b2"), List("a3", "b3"), List("a4", "b4")) // Zip 5 Zip[List].ap.tuple5(List("a1", "b1"), List("a2", "b2"), List("a3", "b3"), List("a4", "b4"), List("a5", "b5")) 

超过5:

 // Zip 6 Zip[List].ap.apply6(List("a1", "b1"), List("a2", "b2"), List("a3", "b3"), List("a4", "b4"), List("a5", "b5"), List("a6", "b6"))((_, _, _, _, _, _)) // Zip 7 Zip[List].ap.apply7(List("a1", "b1"), List("a2", "b2"), List("a3", "b3"), List("a4", "b4"), List("a5", "b5"), List("a6", "b6"), List("a7", "b7"))((_, _, _, _, _, _, _)) ... // Zip 12 Zip[List].ap.apply12(List("a1", "b1"), List("a2", "b2"), List("a3", "b3"), List("a4", "b4"), List("a5", "b5"), List("a6", "b6"), List("a7", "b7"), List("a8", "b8"), List("a9", "b9"), List("a10", "b10"), List("a11", "b11"), List("a12", "b12"))((_, _, _, _, _, _, _, _, _, _, _, _))