Scala:使用cons方法将元素追加到列表

时间:2018-06-30 14:30:56

标签: scala list idiomatic

在阅读Programming in Scala, 3rd Edition时说

  

Class List确实提供了一个“追加”操作,它的写法是:+但是这   很少使用该操作,因为追加到   list随列表的大小线性增长,而前面加上   ::需要固定的时间。

     

如果您想通过添加元素来有效地构建列表,则可以   给它们添加前缀,完成后调用反向。

我试图理解,Scala惯用的方式是什么?与ListBuffer相比,调用List.reverse是否可以接受两次且效率更高(因为ListBuffer可变)?

// Scala Recommended way - but reverse twice?
val alist = List("A", "B")
// cons is O(1)
// This will print (A, B, C)
println(("C" :: alist.reverse).reverse)

// Scala also Recommended: Use ListBuffer
val alb = ListBuffer("A", "B")
alb.append("C")
val clist2 = alb.toList
// This will print (A, B, C)
println(clist2)

// DO NOT do this, its O(n)

val clist3 = alist :+ "C"
// This will print (A, B, C)
println(clist3)

P.S:我在这里不是指代码优化。通常建议使用哪一个,而不会收到 WTH 表达式。

1 个答案:

答案 0 :(得分:0)

另一种实现方式可以是Difference Lists(也可以使用基于Prolog的解释-Understanding Difference Lists)。

这就是我在Scala中实现DList的方式:

abstract class DiffList[A](calculate: List[A] => List[A]) {
  def prepend(s: List[A]): DiffList[A]

  def append(s: List[A]): DiffList[A]

  def result: List[A]
}

final class DiffListImpl[A](listFunc: List[A] => List[A])
    extends DiffList[A](listFunc) {
  def prepend(s: List[A]): DiffListImpl[A] =
    new DiffListImpl[A](listFunc andThen (s ++ _))


  def append(s: List[A]): DiffListImpl[A] =
    new DiffListImpl[A](listFunc andThen (_ ++ s))

  def result: List[A] = listFunc(Nil)
}

并使用它:

val l1 = List(1, 2)
val l2 = List(6, 7)
val l3 = List(3, 4, 5)
val dl = new DiffListImpl[Int](Nil)

val result = dl.prepend(l1).prepend(l2).append(l3).result

Result: List(6, 7, 1, 2, 3, 4, 5)