list 我可以在 Scala 中将两个以上的列表压缩在一起吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1664439/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Can I zip more than two lists together in Scala?
提问by pr1001
Given the following Scala List:
鉴于以下 Scala 列表:
val l = List(List("a1", "b1", "c1"), List("a2", "b2", "c2"), List("a3", "b3", "c3"))
How can I get:
我怎样才能得到:
List(("a1", "a2", "a3"), ("b1", "b2", "b3"), ("c1", "c2", "c3"))
Since zip can only be used to combine two Lists, I think you would need to iterate/reduce the main List somehow. Not surprisingly, the following doesn't work:
由于 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)
Any suggestions one how to do this? I think I'm missing a very simple way to do it.
任何建议如何做到这一点?我想我缺少一种非常简单的方法来做到这一点。
Update:I'm looking for a solution that can take a List of N Lists with M elements each and create a List of M TupleNs.
更新:我正在寻找一种解决方案,它可以采用一个包含 M 个元素的 N 个列表的列表,并创建一个包含 M 个元组的列表。
Update 2:As it turns out it is better for my specific use-case to have a list of lists, rather than a list of tuples, so I am accepting pumpkin's response. It is also the simplest, as it uses a native method.
更新 2:事实证明,我的特定用例最好有一个列表列表,而不是一个元组列表,所以我接受南瓜的回应。它也是最简单的,因为它使用本机方法。
采纳答案by copumpkin
I don't believe it's possible to generate a list of tuples of arbitrary size, but the transpose functiondoes exactly what you need if you don't mind getting a list of lists instead.
我不相信生成任意大小的元组列表是可能的,但是如果您不介意获取列表列表,转置函数可以完全满足您的需求。
回答by Xorlev
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))
For future reference.
备查。
回答by Bijou Trouvaille
So this piece of code won't answer the needs of the OP, and not only because this is a four year old thread, but it does answer the title question, and perhaps someone may even find it useful.
所以这段代码不会满足 OP 的需求,不仅因为这是一个四年前的线程,而且它确实回答了标题问题,也许有人甚至会发现它很有用。
To zip 3 collections:
要压缩 3 个集合:
as zip bs zip cs map {
case ((a,b), c) => (a,b,c)
}
回答by W.P. McNeill
transpose
does the trick. A possible algorithm is:
transpose
诀窍。一种可能的算法是:
def combineLists[A](ss:List[A]*) = {
val sa = ss.reverse;
(sa.head.map(List(_)) /: sa.tail)(_.zip(_).map(p=>p._2 :: p._1))
}
For example:
例如:
combineLists(List(1, 2, 3), List(10,20), List(100, 200, 300))
// => List[List[Int]] = List(List(1, 10, 100), List(2, 20, 200))
The answer is truncated to the size of the shortest list in the input.
答案被截断为输入中最短列表的大小。
combineLists(List(1, 2, 3), List(10,20))
// => List[List[Int]] = List(List(1, 10), List(2, 20))
回答by Ken Bloom
Scala treats all of its different tuple sizes as different classes (Tuple1
, Tuple2
, Tuple3
, Tuple4
,...,Tuple22
) while they do all inherit from the Product
trait, that trait doesn't carry enough information to actually use the data values from the different sizes of tuples if they could all be returned by the same function. (And scala's generics aren't powerful enough to handle this case either.)
Scala 将所有不同的元组大小视为不同的类(Tuple1
, Tuple2
, Tuple3
, Tuple4
,..., Tuple22
),而它们都继承自Product
trait,该 trait 没有携带足够的信息来实际使用来自不同大小的元组的数据值如果它们都可以由同一个函数返回。(而且 scala 的泛型也不足以处理这种情况。)
Your best bet is to write overloads of the zip function for all 22 Tuple sizes. A code generator would probably help you with this.
最好的办法是为所有 22 个元组大小编写 zip 函数的重载。代码生成器可能会帮助您解决这个问题。
回答by Daniel C. Sobral
I don't believe that's possible without being repetitive. For one simple reason: you can't define the returning type of the function you are asking for.
我不相信这是不可能的而不是重复的。原因很简单:您无法定义所请求函数的返回类型。
For instance, if your input was List(List(1,2), List(3,4))
, then the return type would be List[Tuple2[Int]]
. If it had three elements, the return type would be List[Tuple3[Int]]
, and so on.
例如,如果您的输入是List(List(1,2), List(3,4))
,则返回类型将是List[Tuple2[Int]]
。如果它有三个元素,则返回类型将是List[Tuple3[Int]]
,依此类推。
You could return List[AnyRef]
, or even List[Product]
, and then make a bunch of cases, one for each condition.
您可以返回List[AnyRef]
,甚至List[Product]
,然后制作一堆案例,每个条件一个。
As for general List transposition, this works:
至于一般的 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))
}
回答by L4Z
If you don't want to go down the applicative scalaz/cats/(insert your favourite functional lib here) route, pattern matching is the way to go, although the (_, _)
syntax is a bit awkward with nesting, so let's change it:
如果你不想走应用程序的 scalaz/cats/(在此处插入你最喜欢的函数库)路线,模式匹配是要走的路,虽然(_, _)
语法与嵌套有点尴尬,所以让我们改变它:
import scala.{Tuple2 => &}
for (i1 & i2 & i3 & i4 <- list1 zip list2 zip list3 zip list4) yield (i1, i2, i3, i4)
The &
is an arbitrary choice here, anything that looks nice infix should do it. You'll likely get a few raised eyebrows during code review, though.
这&
是一个任意的选择,任何看起来不错的中缀都应该这样做。不过,在代码期间,您可能会有些不悦。
It should also work with anything you can zip
(e.g. Future
s)
它也应该适用于任何你可以使用的东西zip
(例如Future
s)
回答by Mark Lister
product-collectionshas aflatZip
operation up to arity 22.
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))
回答by ZhekaKozlov
With 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"))
For more than 5:
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"))((_, _, _, _, _, _, _, _, _, _, _, _))