循环遍历列表,每次获取越来越多的元素



假设我有一个列表,看起来像

{A, B, C, D, E}  

我想遍历这个列表,每次获得越来越多的元素,所以每次迭代看起来像:

Iteration 1: {A}  
Iteration 2: {A, B}
Iteration 3: {A, B, C}  
Iteration 4: {A, B, C, D}
Iteration 5: {A, B, C, D, E}  

目前,我正在通过以下方式完成此操作:

(1 to list.size).foreach( n => {
val elements = list.take(n)
// Do something with elements
})

但这感觉很混乱。有没有更"scala"的方式来完成这种行为?

您可以使用list.inits

scala> List(1,2,3,4,5).inits.foreach(println)
List(1, 2, 3, 4, 5)
List(1, 2, 3, 4)
List(1, 2, 3)
List(1, 2)
List(1)
List()

要获得您想要的输出,您需要从迭代器创建一个列表,反转它并取尾部以省略空列表:

scala> List(1,2,3,4,5).inits.toList.reverse.tail.foreach(println)
List(1)
List(1, 2)
List(1, 2, 3)
List(1, 2, 3, 4)
List(1, 2, 3, 4, 5)

您可以将foldLeft与链表一起使用来累积元素。

但是,这将颠倒顺序,因此如果您真的关心顺序,则需要调用.reverse函数,这效率不高。

list.foldLeft(Nil : List[String]){(l, n) => {
val elements = n :: l
println(elements)
elements
}}

输出:

List(A)
List(B, A)
List(C, B, A)
List(D, C, B, A)
List(E, D, C, B, A)

这是一个保留顺序但使用ListBuffer的版本,这不是很好

val elems = ListBuffer[String]()
list.foreach{ s => 
elems += s
println(elems)
}

相同,但有折叠

list.foldLeft(ListBuffer[String]()){(elems, s) => 
elems += s
println(elems)
elems
}

输出:

ListBuffer(A)
ListBuffer(A, B)
ListBuffer(A, B, C)
ListBuffer(A, B, C, D)
ListBuffer(A, B, C, D, E)

这是一个递归版本。您需要先反转列表。

@tailrec
def doIt(l: List[Int], acc: List[List[Int]] = Nil): List[List[Int]] = l match {
case Nil => acc
case h :: t => doIt(t, List(h) :: acc.map(l => h :: l))
}

doIt(List(1,2,3).reverse).foreach(println)
// output
List(1)
List(1, 2)
List(1, 2, 3)

最新更新