仅转换Scala列表的最后一个元素

时间:2016-03-07 11:07:51

标签: scala

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

6 个答案:

答案 0 :(得分:8)

另一种类似的方式是:

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

答案 1 :(得分:2)

你可以这样做:

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

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

答案 2 :(得分:1)

也许您正在寻找类似的东西: list.init :+ changes(list.last) 但是@mfirry提供的示例将更快更安全地工作。 为了获得良好的表现,您可以使用矢量代替列表

答案 3 :(得分:0)

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

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

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

答案 4 :(得分:0)

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

  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)

}

答案 5 :(得分:-1)

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

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