我正在尝试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
Run Code Online (Sandbox Code Playgroud)
我得到了什么:
List[(((Int, Char), String), Boolean)] =
List((((1,a),Alpha),true), (((2,b),Beta),false), (((3,c),Gamma),false))
Run Code Online (Sandbox Code Playgroud)
但是我想得到一系列扁平元组:
List[(Int, Char, String, Boolean)] =
List((1,a,Alpha,true), (2,b,Beta,false), (3,c,Gamma,false))
Run Code Online (Sandbox Code Playgroud)
我现在能做到:
List(ints, chars, strings, bools).transpose
Run Code Online (Sandbox Code Playgroud)
但它返回的是弱类型List[List[Any]].我也可以做(ints, chars, strings).zipped,但zipped只适用于2元组和3元组.
有没有办法轻松地压缩(任意)数量的等长序列?
Jes*_*per 11
这是解决您的示例的一种方法,但这不适用于任意数量的序列.
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
Run Code Online (Sandbox Code Playgroud)
对于任意长度的元组,我认为不可能这样做,至少不是这种解决方案.元组是强类型的,并且类型系统不允许你指定可变数量的类型参数,据我所知,这使得无法制作一个通用版本f2并且f3需要任意长度的元组((A,B),C,D,...)(会返回一个元组(A,B,C,D,...)).
如果有指定可变数量的类型参数的方式,我们就不需要特质Tuple1,Tuple2...... Tuple22在Scala的标准库.
我会创建一个代表数据集的类:
case class DataSet(int: Int, char: Char, string: String, bool: Boolean)
Run Code Online (Sandbox Code Playgroud)
这为访问值提供了更好的名称,而不是_N我们在元组中的名称.如果列表可以具有不同的大小,则应选择最短的列表:
val min = List(ints, chars, strings, bools).map(_.size).min
Run Code Online (Sandbox Code Playgroud)
现在可以提取数据:
val dataSets = (0 until min) map { i => DataSet(ints(i), chars(i), strings(i), bools(i)) }
Run Code Online (Sandbox Code Playgroud)
当原始列表可以包含许多值时,最好将它们设置为a,IndexedSeq以便访问时间为O(1).
我认为模式匹配是一个不错的选择
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))**
Run Code Online (Sandbox Code Playgroud)
或者您也可以添加类型
(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))**
Run Code Online (Sandbox Code Playgroud)
使用无形,你可以这样做:
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))
Run Code Online (Sandbox Code Playgroud)
(不确定,如果定义了更多的隐含,可以避免转发map和来回转换)
[ 编辑:这部分不再适用.
请注意,无形文档说,Tuple4目前只支持转换.您必须手动创建HLists.]