Scala:一次完成映射和解压列表

Scala:一次完成映射和解压列表,scala,list,dictionary,collections,tuples,Scala,List,Dictionary,Collections,Tuples,我有一个元组列表,如下所示: [(8, 3, 9), (10, 3, 0), (-37, 4, 1)] 我想映射这个列表,同时解压它在一次通过。下面是一个有两个过程的示例(或者至少我强烈假设它需要两个过程,如果不是,那么我们在这里完成了:D) 当然,我可以通过在列表上循环并附加到集合中,以命令式的方式来实现这一点,但有没有一种方法可以以简洁的功能方式实现这一点?我猜我基本上需要一个懒散的地图,然后是一个急切的解压,这对于你所说的问题是非常具体的;它不能解决更普遍的问题。尝试: val (lis

我有一个元组列表,如下所示:

[(8, 3, 9), (10, 3, 0), (-37, 4, 1)]
我想映射这个列表,同时解压它在一次通过。下面是一个有两个过程的示例(或者至少我强烈假设它需要两个过程,如果不是,那么我们在这里完成了:D)


当然,我可以通过在列表上循环并附加到集合中,以命令式的方式来实现这一点,但有没有一种方法可以以简洁的功能方式实现这一点?我猜我基本上需要一个懒散的
地图
,然后是一个急切的
解压
,这对于你所说的问题是非常具体的;它不能解决更普遍的问题。尝试:

val (list1, list2, _) = l.unzip3

编辑
公平地说,在定位了实现
scala.collection.generic.GenericTraversableTemplate.unzip3
之后,它是一个非常没有功能的循环,它构建了3个列表并返回它们,这与原始问题中描述的非常相似。至少这是一个问题,而不仅仅是埋葬两个问题。

这对于你所说的问题是非常具体的;它不能解决更普遍的问题。尝试:

val (list1, list2, _) = l.unzip3

编辑
公平地说,在定位了实现
scala.collection.generic.GenericTraversableTemplate.unzip3
之后,它是一个非常没有功能的循环,它构建了3个列表并返回它们,这与原始问题中描述的非常相似。至少是一个关卡,而不仅仅是埋葬两个关卡。

总是有
折叠

val (list1, list2) = l.foldRight((List.empty[Int],List.empty[Int])){
  case ((a,b,_),(l1,l2)) => (a::l1,b::l2)
}

总是有
折叠

val (list1, list2) = l.foldRight((List.empty[Int],List.empty[Int])){
  case ((a,b,_),(l1,l2)) => (a::l1,b::l2)
}
在函数中使用
解压
在Scala中,
unzip
操作将函数作为一个隐式参数来生成该对,这样您就可以一次将
map
unzip
。下面是它在
列表中的显示方式:

def unzip[A1, A2](implicit asPair: (A) => (A1, A2)): (List[A1], List[A2])
通过传递您自己的
asPair
函数,您可以实现所需的结果:

scala> val l = List((8, 3, 9), (10, 3, 0), (-37, 4, 1))
val l: List[(Int, Int, Int)] = List((8,3,9), (10,3,0), (-37,4,1))

scala> val (list1, list2) = l.unzip(el => (el._1, el._2))
val list1: List[Int] = List(8, 10, -37)
val list2: List[Int] = List(3, 3, 4)
算法复杂性
unzip
函数的源代码位于trait
scala.collection.IterableOps
文件中:

如果我读对了,这个列表实际上被遍历了两次:每生成一个列表就遍历一次

但是,在最初的解决方案中,该列表被遍历了三次:一次用于
map
操作,两次用于
unzip
操作,因此我的解决方案仍然是一个改进

@jwvh建议的使用
foldRight
的解决方案似乎只遍历列表一次,但是
foldRight
的开销是最初反转列表(以便从列表的头部获取)。所以我猜我的解决方案有着完全相同的算法复杂性。(如果我错了,请纠正我。)

使用带有函数的
解压

在Scala中,
unzip
操作将函数作为一个隐式参数来生成该对,这样您就可以一次将
map
unzip
。下面是它在
列表中的显示方式:

def unzip[A1, A2](implicit asPair: (A) => (A1, A2)): (List[A1], List[A2])
通过传递您自己的
asPair
函数,您可以实现所需的结果:

scala> val l = List((8, 3, 9), (10, 3, 0), (-37, 4, 1))
val l: List[(Int, Int, Int)] = List((8,3,9), (10,3,0), (-37,4,1))

scala> val (list1, list2) = l.unzip(el => (el._1, el._2))
val list1: List[Int] = List(8, 10, -37)
val list2: List[Int] = List(3, 3, 4)
算法复杂性
unzip
函数的源代码位于trait
scala.collection.IterableOps
文件中:

如果我读对了,这个列表实际上被遍历了两次:每生成一个列表就遍历一次

但是,在最初的解决方案中,该列表被遍历了三次:一次用于
map
操作,两次用于
unzip
操作,因此我的解决方案仍然是一个改进

@jwvh建议的使用
foldRight
的解决方案似乎只遍历列表一次,但是
foldRight
的开销是最初反转列表(以便从列表的头部获取)。所以我猜我的解决方案有着完全相同的算法复杂性。(如果我错了,请纠正我。)