给出以下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只能用于组合两个列表,我认为你需要以某种方式迭代/减少主列表。毫不奇怪,以下不起作用:
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)
任何建议如何做到这一点?我想我错过了一种非常简单的方法。
更新:我正在寻找一种解决方案,可以获取每个包含M个元素的N个列表列表,并创建一个M个元组列表。
更新2:事实证明,我的特定用例最好有一个列表列表,而不是元组列表,所以我接受南瓜的回复。它也是最简单的,因为它使用本机方法。
答案 0 :(得分:199)
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))
供将来参考。
答案 1 :(得分:31)
我不相信可以生成任意大小的元组列表,但如果您不介意获取列表列表,则transpose function完全符合您的要求。
答案 2 :(得分:26)
所以这段代码不会满足OP的需求,不仅因为这是一个有四年历史的线程,而且它确实回答了标题问题,也许有人甚至可能觉得它很有用。
要压缩3个集合:
as zip bs zip cs map {
case ((a,b), c) => (a,b,c)
}
答案 3 :(得分:12)
是的,zip3。
答案 4 :(得分:5)
Scala将其所有不同的元组大小视为不同的类(Tuple1
,Tuple2
,Tuple3
,Tuple4
,...,Tuple22
)它们都是从Product
特征继承的,如果它们都可以由同一个函数返回,那么特征没有足够的信息来实际使用来自不同大小的元组的数据值。 (scala的泛型也不足以处理这种情况。)
最好的办法是为所有22个元组大小编写zip函数的重载。代码生成器可能会帮助您解决此问题。
答案 5 :(得分:5)
我不相信这是可能的而不是重复。原因很简单:您无法定义要求的函数的返回类型。
例如,如果您的输入是List(List(1,2),List(3,4)),那么返回类型将是List [Tuple2 [Int]]。如果它有三个元素,则返回类型为List [Tuple3 [Int]],依此类推。
你可以返回List [AnyRef],甚至是List [Product],然后制作一堆案例,每个条件一个。
对于一般的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))
}
答案 6 :(得分:5)
transpose
可以解决问题。一种可能的算法是:
def combineLists[A](ss:List[A]*) = {
val sa = ss.reverse;
(sa.head.map(List(_)) /: sa.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(1, 10, 100), List(2, 20, 200))
答案被截断为输入中最短列表的大小。
combineLists(List(1, 2, 3), List(10,20))
// => List[List[Int]] = List(List(1, 10), List(2, 20))
答案 7 :(得分:5)
如果你不想下去应用scalaz / cats /(在这里插入你喜欢的函数库)路由,模式匹配是要走的路,尽管(_, _)
语法有点尴尬嵌套,所以让我们改变它:
import scala.{Tuple2 => &}
for (i1 & i2 & i3 & i4 <- list1 zip list2 zip list3 zip list4) yield (i1, i2, i3, i4)
&
在这里是一个随意的选择,任何看起来很好的中缀都应该这样做。但是,在代码审查期间,您可能会得到一些眉毛。
它也适用于您可以zip
(例如Future
s)
答案 8 :(得分:2)
product-collections有一个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))
答案 9 :(得分:1)
如果你知道输入的List有多长,你可以将列表加入一个Tuple,使用Tuple的.zipped
方法:
val l = List(List("a1", "b1", "c1"), List("a2", "b2", "c2"), List("a3", "b3", "c3"))
println(l match {
case l1::l2::l3::_ => (l1,l2,l3).zipped.toList
case _ => throw new IllegalArgumentException("List is not the right length")
}) // List((a1,a2,a3), (b1,b2,b3), (c1,c2,c3))
不推荐使用上述解决方案 - 使用lazyZip 代替:
val l = List(List("a1", "b1", "c1"), List("a2", "b2", "c2"), List("a3", "b3", "c3"))
println(l match {
case l1::l2::l3::_ => (l1 lazyZip l2 lazyZip l3).toList
case _ => throw new IllegalArgumentException("List is not the right length")
}) // List((a1,a2,a3), (b1,b2,b3), (c1,c2,c3))
答案 10 :(得分:0)
使用Scalaz:
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"))((_, _, _, _, _, _, _, _, _, _, _, _))