【问题标题】:Zip two lists of different lengths with default element to fill使用要填充的默认元素压缩两个不同长度的列表
【发布时间】:2016-02-15 09:27:18
【问题描述】:

假设我们有以下不同大小的列表:

val list1 = ("a", "b", "c")
val list2 = ("x", "y")

现在我想合并这两个列表并创建一个新列表,其中包含正在连接的字符串元素:

val desiredResult = ("ax", "by", "c")

我试过了

val wrongResult = (list1, list2).zipped map (_ + _)

按照here 的建议,但这并没有按预期工作,因为 zip 会丢弃较长列表中无法匹配的那些元素。

我该如何解决这个问题?如果一个列表较长,有没有办法压缩列表并给出“默认元素”(如本例中的空字符串)?

【问题讨论】:

    标签: scala functional-programming


    【解决方案1】:

    你要找的方法是.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,""))
    

    .zipAll 接受 3 个参数:

    • 用于压缩的迭代器
    • this(调用集合.zipAll)时的默认值更短
    • 其他集合较短时的默认值

    【讨论】:

    • 谢谢!现在它适用于这个解决方案:list1.zipAll(list2, "", "") map ({ case (y, x) => y + x }),但不像以前使用list1.zipAll(list2, "", "") map (_ + _)。为什么我不能像压缩函数一样使用 zipAll 的短语法?
    • @ForceOfWill: (list1, list2).zipped 返回一个Tuple2Zipped,其中.map 接受一个f:(El1,El2)=>B(即一个接受2 个参数的函数)。 List[A].map 采用f: A => B,即只有1 个参数(在这种情况下是Tuple2)。不幸的是,这意味着 _ + _(这是一个带有 2 个参数的函数)不能在这里应用。
    • 对三个论点的解释是最好的部分。谢谢
    【解决方案2】:

    基于 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) 
      }
    }
    

    例如

    Seq(1,2).zipAll2(Seq(3,4,5),10,20)
    List((1,3), (2,4), (10,5))
    

    list1.zipAll2(list2, "", "")
    List((a,x), (b,y), (c,""))
    

    递归版本,

    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) 
      }
    }
    

    具有默认 xd 和默认 yd 值。

    【讨论】:

      猜你喜欢
      • 2019-12-12
      • 1970-01-01
      • 2017-08-30
      • 1970-01-01
      • 2019-11-30
      • 1970-01-01
      • 1970-01-01
      • 2016-12-05
      • 2018-08-14
      相关资源
      最近更新 更多