For*_*ill 14 functional-programming scala
假设我们有以下不同大小的列表:
val list1 = ("a", "b", "c")
val list2 = ("x", "y")
Run Code Online (Sandbox Code Playgroud)
现在我想合并这两个列表并创建一个新的列表,其中串联的字符串元素:
val desiredResult = ("ax", "by", "c")
Run Code Online (Sandbox Code Playgroud)
我试过了
val wrongResult = (list1, list2).zipped map (_ + _)
Run Code Online (Sandbox Code Playgroud)
正如这里提出的那样,但是这不能按预期工作,因为zip会丢弃那些无法匹配的较长列表中的元素.
我怎么解决这个问题?有没有办法压缩列表并给出一个"默认元素"(如本例中的空字符串),如果一个列表更长?
Mar*_*rth 36
您正在寻找的方法是.zipAll:
scala> val list1 = List("a", "b", "c")
list1: List[String] = List(a, b, c)
scala> val list2 = List("x", "y")
list2: List[String] = List(x, y)
scala> list1.zipAll(list2, "", "")
res0: List[(String, String)] = List((a,x), (b,y), (c,""))
Run Code Online (Sandbox Code Playgroud)
.zipAll 需要3个参数:
this(.zipAll调用集合)的默认值更短基于 API 的方法zipAll是可行的,但您可以实现它(作为练习),例如,如下所示,
implicit class OpsSeq[A,B](val xs: Seq[A]) extends AnyVal {
def zipAll2(ys: Seq[B], xDefault: A, yDefault: B) = {
val xs2 = xs ++ Seq.fill(ys.size-xs.size)(xDefault)
val ys2 = ys ++ Seq.fill(xs.size-ys.size)(yDefault)
xs2.zip(ys2)
}
}
Run Code Online (Sandbox Code Playgroud)
因此例如
Seq(1,2).zipAll2(Seq(3,4,5),10,20)
List((1,3), (2,4), (10,5))
Run Code Online (Sandbox Code Playgroud)
和
list1.zipAll2(list2, "", "")
List((a,x), (b,y), (c,""))
Run Code Online (Sandbox Code Playgroud)
递归版本,
def zipAll3[A,B](xs: Seq[A], ys: Seq[B], xd: A, yd: B): Seq[(A,B)] = {
(xs,ys) match {
case (Seq(), Seq()) => Seq()
case (x +: xss, Seq()) => (x,yd) +: zipAll3(xss, Seq(), xd, yd)
case (Seq(), y +: yss) => (xd,y) +: zipAll3(Seq(), yss, xd, yd)
case (x +: xss, y +: yss) => (x,y) +: zipAll3(xss, yss, xd, yd)
}
}
Run Code Online (Sandbox Code Playgroud)
带有默认值xd和默认yd值。
| 归档时间: |
|
| 查看次数: |
9175 次 |
| 最近记录: |