假设我有一个列表,看起来像
{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)