【问题标题】:Loop over a List getting an increasing number of elements each time循环遍历列表,每次获取越来越多的元素
【发布时间】:2020-05-28 17:02:30
【问题描述】:

假设我有一个看起来像这样的列表

{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”的方式来完成这种行为?

【问题讨论】:

    标签: scala collections


    【解决方案1】:

    你可以使用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)
    

    【讨论】:

      【解决方案2】:

      您可以使用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)
      

      【讨论】:

        【解决方案3】:

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

        @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)
        

        【讨论】:

          最近更新 更多