【问题标题】:Transform only the last element of a Scala list仅转换 Scala 列表的最后一个元素
【发布时间】:2016-03-07 19:49:12
【问题描述】:

是否可以仅转换类似于此线程的 Scala 列表的最后一个元素?- Transform only the first element of a Scala list

【问题讨论】:

    标签: scala


    【解决方案1】:

    另一种类似的方式是:

    l match{
      case Nil            => Nil
      case xs :+ y => xs :+ change(y)
    }
    

    【讨论】:

      【解决方案2】:

      你可以这样做:

      val l2 = l1.dropRight(1) :+ change(l1.last)
      

      话虽如此,请记住,Lists 是一种很好的数据结构,用于访问其头部(并对其尾部进行操作),但对于随机和直接访问来说效率非常低。如果您需要访问最后一个元素,使用直接访问结构(如数组或向量)会更有效。

      【讨论】:

      • 这会遍历同一个列表两次。
      • 实际上是3次,因为插入到最后一个位置。我已经在强调,为此使用列表根本不是最佳选择。
      【解决方案3】:

      也许您正在寻找类似的东西: list.init :+ changes(list.last) 但是@mfirry 提供的示例将更快、更安全地工作。 为了获得良好的性能,您可以使用 Vector 而不是 List

      【讨论】:

        【解决方案4】:

        仅迭代列表两次的版本(改编自链接问题中接受的答案)。而且很明显:)

        val l2 = (l1.reverse match{
          case Nil   => Nil
          case x::xs => change(x)::xs
        }).reverse
        

        如果你有一个不可变的列表,那就不可能比迭代两次更好。一次找到最后的元素,第二次用改变的元素替换它

        【讨论】:

          【解决方案5】:

          更通用的版本(仍然只接受输入中的列表)

            def mutateLast[A, R](l: List[A])(f: A => A)(implicit cb: CanBuildFrom[List[A], A, R]): R = {
              val builder = cb(l)
          
              @annotation.tailrec
              def loop(l: List[A]): R = l match {
                case Nil => builder.result()
                case h :: Nil =>
                  builder += f(h)
                  builder.result()
                case h :: t =>
                  builder += h
                  loop(t)
              }
          
              loop(l)
            }
          
            val l = List(1, 2, 3)
            val mutated = mutateLast(l)(x => x * 2)
            println(mutated)
          

          }

          【讨论】:

            【解决方案6】:

            必须承认,List 的这段代码效率很低。 splitAt 函数具有复杂性 O(n)... 但同样的复杂性具有 .last 函数。假设为了获得更好的性能,您应该使用一些索引集合而不是列表。

              l.splitAt(l.size - 1) match {
                case (l1, l2) => l1 ::: l2.map(modify(_))
              }
            

            【讨论】:

              猜你喜欢
              • 2012-05-22
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2010-11-13
              • 2022-01-07
              • 2018-03-10
              相关资源
              最近更新 更多