scala 压缩多个序列
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9632094/
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
Zip multiple sequences
提问by Tomasz Nurkiewicz
I am trying to zipmultiple sequences to form a long tuple:
我正在尝试zip多个序列来形成一个长元组:
val ints = List(1,2,3)
val chars = List('a', 'b', 'c')
val strings = List("Alpha", "Beta", "Gamma")
val bools = List(true, false, false)
ints zip chars zip strings zip bools
What I get:
我得到的:
List[(((Int, Char), String), Boolean)] =
List((((1,a),Alpha),true), (((2,b),Beta),false), (((3,c),Gamma),false))
However I would like to get a sequence of flattuples:
但是我想获得一系列扁平元组:
List[(Int, Char, String, Boolean)] =
List((1,a,Alpha,true), (2,b,Beta,false), (3,c,Gamma,false))
I now I can do:
我现在可以这样做:
List(ints, chars, strings, bools).transpose
But it returns weakly typed List[List[Any]]. Also I can do (ints, chars, strings).zipped, but zippedworks only on 2-tuples and 3-tuples.
但它返回弱类型的List[List[Any]]。我也可以做(ints, chars, strings).zipped,但zipped只适用于 2 元组和 3 元组。
Is there a way to zip (arbitrary) number of equal-length sequences easily?
有没有办法轻松压缩(任意)数量的等长序列?
采纳答案by Jesper
Here's one way to solve your example, but this is not for an arbitrary number of sequences.
这是解决您的示例的一种方法,但这不适用于任意数量的序列。
val ints = List(1,2,3)
val chars = List('a', 'b', 'c')
val strings = List("Alpha", "Beta", "Gamma")
val bools = List(true, false, false)
val input = ints zip chars zip strings zip bools
// Flattens a tuple ((A,B),C) into (A,B,C)
def f2[A,B,C](t: ((A,B),C)) = (t._1._1, t._1._2, t._2)
// Flattens a tuple ((A,B),C,D) into (A,B,C,D)
def f3[A,B,C,D](t: ((A,B),C,D)) = (t._1._1, t._1._2, t._2, t._3)
input map f2 map f3
I don't think it is possible to do it generically for tuples of arbitrary length, at least not with this kind of solution. Tuples are strongly-typed, and the type system doesn't allow you to specify a variable number of type parameters, as far as I know, which makes it impossible to make a generalized version of f2and f3that takes a tuple of arbitrary length ((A,B),C,D,...)(that would return a tuple (A,B,C,D,...)).
我认为不可能对任意长度的元组进行一般性的处理,至少不能使用这种解决方案。元组是强类型的,并且类型系统不允许您指定可变数量的类型参数,据我所知,这使得无法制作具有任意长度的元组的f2和的通用版本(即将返回一个元组)。f3((A,B),C,D,...)(A,B,C,D,...)
If there were a way to specify a variable number of type parameters, we wouldn't need traits Tuple1, Tuple2, ... Tuple22in Scala's standard library.
如果有一种方法可以指定可变数量的类型参数,我们就不需要Scala 标准库中的traits Tuple1, Tuple2, ... Tuple22。
回答by igx
I think pattern matching is a good option
我认为模式匹配是一个不错的选择
val ints = List(1,2,3)
val chars = List('a', 'b', 'c')
val strings = List("Alpha", "Beta", "Gamma")
val bools = List(true, false, false)
(ints zip chars zip strings zip bools) map { case (((i,c),s),b) => (i,c,s,b)}
**res1: List[(Int, Char, java.lang.String, Boolean)] = List((1,a,Alpha,true), (2,b,Beta,false), (3,c,Gamma,false))**
or you can add type as well
或者你也可以添加类型
(ints zip chars zip strings zip bools) map {case (((i:Int,c:Char),s:String),b:Boolean) => (i,c,s,b)}
**res2: List[(Int, Char, java.lang.String, Boolean)] = List((1,a,Alpha,true), (2,b,Beta,false), (3,c,Gamma,false))**
回答by kiritsuku
I would create a class which represents the data sets:
我将创建一个代表数据集的类:
case class DataSet(int: Int, char: Char, string: String, bool: Boolean)
This brings nicer names for accessing the values instead of _Nwe have in tuples. If the lists can have different sizes the shortest should be chosen:
这为访问值带来了更好的名称,而不是_N我们在元组中的名称。如果列表可以有不同的大小,则应选择最短的:
val min = List(ints, chars, strings, bools).map(_.size).min
Now it is possible to extract the data:
现在可以提取数据:
val dataSets = (0 until min) map { i => DataSet(ints(i), chars(i), strings(i), bools(i)) }
When the original lists can contain a lot of values it is better to make them to a IndexedSeqso that the access time is O(1).
当原始列表可以包含很多值时,最好将它们设置为 a,IndexedSeq以便访问时间为 O(1)。
回答by Debilski
Using shapeless, you could do:
使用shapeless,您可以执行以下操作:
import shapeless.Tuples._
val ints = (1, 2, 3)
val chars = ('a', 'b', 'c')
val megatuple = (ints, chars)
val megahlist = (megatuple hlisted) map hlisted
val transposed = (mhlist transpose) map tupled tupled
scala> transposed
res: ((Int, Char), (Int, Char), (Int, Char)) = ((1,a),(2,b),(3,c))
(not sure, if there are more implicts defined which lets you avoid the mapand back-and-forth conversions)
(不确定,如果定义了更多隐含,可以避免map来回转换)
[Edit: This part is not true anymore.
[编辑:这部分不再正确。
Note that the shapeless docs say, only conversions up to Tuple4are currently supported. You'd have to manually create the HLists then.]
请注意,shapeless 文档说,Tuple4目前仅支持最多转换。然后您必须手动创建 HList。]
回答by ziggystar
I share Jesper's opinion that this is not possible in general, since each tuple arity is represented as separate class in source code, so you have to write separate code to access them unless using a code generator.
我同意 Jesper 的观点,即这在一般情况下是不可能的,因为每个元组元组在源代码中表示为单独的类,因此除非使用代码生成器,否则您必须编写单独的代码来访问它们。
But I want to add another possible solution. If you want to preserve the typing of your tuple entries, but are otherwise interested in a more collection-like type, maybe HLists (heterogenous lists) are for you. You can google hlist scalafor implementations and explanations.
但我想添加另一个可能的解决方案。如果您想保留元组条目的类型,但对更像集合的类型感兴趣,也许 HLists(异构列表)适合您。你可以谷歌hlist scala搜索实现和解释。
回答by Mark Lister
Using product-collections
使用产品集合
scala> ints flatZip chars flatZip strings flatZip bools
res0: org.catch22.collections.immutable.CollSeq4[Int,Char,String,Boolean] =
CollSeq((1,a,Alpha,true),
(2,b,Beta,false),
(3,c,Gamma,false))
This currently works for arity 1 - 22. As you can see the types are preserved.
这目前适用于 arity 1 - 22。如您所见,类型被保留。
回答by Shirish Namdeo
Here is another solution which would work for your problem.
这是另一种可以解决您的问题的解决方案。
ints zip chars zip strings zip bools map{ case (((a, b), c), d) => (a,b,c,d)}

