在Scala中实现“zipLongest”的最佳方法

4
我需要在Scala中实现一个"zipLongest"函数;即将两个序列组合成一对,如果其中一个序列比另一个序列长,则使用默认值。(与标准的zip方法不同,后者只会截断到最短的序列。)
我直接按以下方式实现:
def zipLongest[T](xs: Seq[T], ys: Seq[T], default: T): Seq[(T, T)] = (xs, ys) match {
  case (Seq(), Seq())           => Seq()
  case (Seq(), y +: rest)       => (default, y) +: zipLongest(Seq(), rest, default)
  case (x +: rest, Seq())       => (x, default) +: zipLongest(rest, Seq(), default)
  case (x +: restX, y +: restY) => (x, y) +: zipLongest(restX, restY, default)
}

有更好的方法吗?

2个回答

8
使用 zipAll
scala> val l1 = List(1,2,3)
l1: List[Int] = List(1, 2, 3)

scala> val l2 = List("a","b")
l2: List[String] = List(a, b)

scala> l1.zipAll(l2,0,".")
res0: List[(Int, String)] = List((1,a), (2,b), (3,.))

如果您想为第一个和第二个序列使用相同的默认值:

scala> def zipLongest[T](xs:Seq[T], ys:Seq[T], default:T) = xs.zipAll(ys, default, default)
zipLongest: [T](xs: Seq[T], ys: Seq[T], default: T)Seq[(T, T)]

scala> val l3 = List(4,5,6,7)
l3: List[Int] = List(4, 5, 6, 7)

scala> zipLongest(l1,l3,0)
res1: Seq[(Int, Int)] = List((1,4), (2,5), (3,6), (0,7))

6
您可以将其作为一行代码来完成:
xs.padTo(ys.length, x).zip(ys.padTo(xs.length, y))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接