我想在列表中压缩偶数和奇数元素以生成对的列表,如:
["A", "B", "C", "D", "E", "F"] -> [("A", "B"), ("C", "D"), ("E", "F")]
以优雅的功能方式执行此操作的最简洁表达是什么?
答案 0 :(得分:7)
在2.8中,你可能会使用方法:
scala> val a = "ABCDEF".toList.map(_.toString)
a: List[java.lang.String] = List(A, B, C, D, E, F)
scala> a.grouped(2).partialMap{ case List(a,b) => (a,b) }.toList
res0: List[(java.lang.String, java.lang.String)] = List((A,B), (C,D), (E,F))
(这是2.8.0 Beta1;最新的主干collect
代替partialMap
。)
在2.7中 - 而不是2.8中的亚军 - 你可以像legoscia那样创建一个递归方法:
def zipPairs[A](la : List[A]): List[(A,A)] = la match {
case a :: b :: rest => (a,b) :: zipPairs(rest)
case _ => Nil
}
scala> zipPairs(a)
res1: List[(java.lang.String, java.lang.String)] = List((A,B), (C,D), (E,F))
编辑:这是另一种适用于2.7的简洁方法:
scala> (a zip a.drop(1)).zipWithIndex.filter(_._2 % 2 == 0).map(_._1)
res2: List[(java.lang.String, java.lang.String)] = List((A,B), (C,D), (E,F))
(请注意使用drop(1)
代替tail
,因此它适用于空列表。)
答案 1 :(得分:4)
未测试:
def ziptwo(l: List[String]): List[(String, String)] = l match {
case Nil => Nil
case a :: b :: rest =>
Pair(a,b) :: ziptwo(rest)
}
答案 2 :(得分:4)
def pairs[T](xs: List[T]) =
xs.grouped(2)
.map{case List(a, b) => (a,b)}
.toList
答案 3 :(得分:3)
让每个人想出最明显的做法的唯一好处就是我必须更加努力地思考替代解决方案。所以这里有一个适用于Scala 2.8。在Scala 2.7上,将view
替换为projection
。
def everyNofM[T](l: List[T], n: Int, m: Int) =
l.view.zipWithIndex.filter(_._2 % m == n).map(_._1)
def evens[T](l: List[T]) = everyNofM(l, 0, 2)
def odds[T](l: List[T]) = everyNofM(l, 1, 2)
def zip[T](l: List[T]) = evens(l) zip odds(l) toList
严格来说,view
/ projection
是不必要的,但它可以避免不必要地创建中间结果。
其他有趣的方式:
def zip[T](l: List[T]) = l.indices.partition(_ % 2 == 0).zipped.map(
(x: Int, y: Int) => (l(x), l(y))
).toList
def zip[T](l: List[T]) = l.zipWithIndex.partition(_._2 % 2 == 0).zipped.map(
(x, y) => (x._1, y._1)
)
PS:奖励指向获得双关语的人。 ; - )
答案 4 :(得分:1)
def pairify[T](list: List[T]): List[(T, T)] = list match {
case Nil => Nil
case x :: y :: xs => (x, y) :: pairify(xs)
case _ => error("odd length list!")
}
答案 5 :(得分:1)
这允许不完整的对:
def pairwise [T] (xs: List[T]) : List [(Option[T], Option[T])] = xs match {
case (x :: y :: xsr) => (Some (x), Some (y)) :: pairwise (xsr)
case (x :: Nil) => List ((Some (x), None))
case (_) => Nil }
答案 6 :(得分:0)
使用Scala 2.11.8版本
val s = Seq("A", "B", "C", "D", "E", "F")
s.sliding(2,2).map( l => (l.head,l.tail.head) ).toArray
输出:
Array[(String, String)] = Array((A,B), (C,D), (E,F))
如果输入序列可以包含奇数个元素,则需要更多详细信息:
val s = Seq("A", "B", "C", "D", "E", "F", "ODD")
val defaultValue = "_"
s.sliding(2,2).map( l => (l.head,l.tail.headOption.getOrElse(defaultStr)) ).toArray
输出:
Array[(String, String)] = Array((A,B), (C,D), (E,F), (ODD,_))