【问题标题】:Writing an iterator for a 2D array为二维数组编写迭代器
【发布时间】:2011-07-18 05:05:24
【问题描述】:

我正在尝试为二维数组编写迭代器。以下是我想出的。

  def rowsTest() {
    val array = Array(
      Array(9, 11, 4, 89),
      Array(7, 62, 34, 2),
      Array(3, 4, 5, 12),
      Array(13, 4, 5, 12),
      Array(3, 24, 5, 12),
      Array(3, 4, 35, 12)
    )
    def rows: Iterator[Iterator[Int]] = {
      new Iterator[Iterator[Int]] {
        private var rowIndex = 0

        def hasNext: Boolean = rowIndex < 6

        def next: Iterator[Int] = {
          val rowIterator = new Iterator[Int] {
            private var columnIndex = 0

            def next: Int = {
              val p = array(columnIndex)(rowIndex)
              columnIndex += 1
              println("ColIndex = "+ columnIndex.toString)
              p
            }

            def hasNext: Boolean = columnIndex < 4
          }
          rowIndex += 1
          println("RowIndex = "+ rowIndex.toString)
          rowIterator
        }
      }
    }
    for(row <- rows; elem <- row)
      println(elem)
  }

上面的代码在运行时会跳过第一行,当所有元素都被打印出来时也会给出ArrayIndexOutOfBoundsException。你能帮我弄清楚我哪里出错了吗?

谢谢你,
悉达多·雷纳。

【问题讨论】:

    标签: arrays scala iterator


    【解决方案1】:

    下面的代码怎么样?

    val array = Array(Array(1,2,3),Array(4,5,6),Array(7,8,9))
    array.view.flatten.iterator
    

    如 REPL 中测试的那样,它可以工作。虽然我不知道我是否通过“视图”实现了我的意图。欢迎任何cmets。

    编辑

    我忘了作者想要一个嵌套迭代器。

    array.iterator.map(_.iterator)
    

    这当然可以在没有“视图”和开销的情况下工作。

    【讨论】:

      【解决方案2】:

      我无法从你的代码中看出你真正想要做什么。

      如果你想用迭代器的迭代器遍历你的数组,已经有一个简单的方法来做到这一点:

      val a2d = Array.tabulate(4,4)((i,j)=>4*i+j)
      a2d.iterator.map(_.iterator)
      

      如果你决定要一个迭代器,你也可以这样做:

      a2d.iterator.flatMap(_.iterator)
      

      如果你想遍历 columns 即使数组是行优先的顺序,那么你还有更多的工作要做(我认为这是你想要做的,但是你混合了你的数组索引,也许还有其他一些东西):

      def iterateColumns(aai: Array[Array[Int]]) = new Iterator[Iterator[Int]] {
        private[this] var j = -1
        private[this] val shortest = if (aai.length==0) 0 else aai.map(_.length).min
        def hasNext = j+1 < shortest
        def next = {
          j += 1
          new Iterator[Int] {
            private[this] var i = -1
            def hasNext = i+1 < aai.length
            def next = {
              i += 1
              aai(i)(j)
            }
          }
        }
      }
      

      现在可以

      scala> for (row <- a2d.iterator.map(_.iterator)) println(row.mkString(" "))
      0 1 2 3
      4 5 6 7
      8 9 10 11
      12 13 14 15
      
      scala> for (col <- iterateColumns(a2d)) println(col.mkString(" "))
      0 4 8 12
      1 5 9 13
      2 6 10 14
      3 7 11 15
      

      (您还应该能够使用a2d.view.transpose.iterator.map(_.iterator) 来避免复制,但不幸的是,这看起来不像您在 2.8.1 中希望的那样工作。)

      【讨论】:

        【解决方案3】:

        如果你想以命令式的方式手工制作:

          def rowsTest() {
            val array = Array(
              Array(9, 11, 4, 89),
              Array(7, 62, 34, 2),
              Array(3, 4, 5, 12),
              Array(13, 4, 5, 12),
              Array(3, 24, 5, 12),
              Array(3, 4, 35, 12)
            )
            def rows: Iterator[Iterator[Int]] = {
              new Iterator[Iterator[Int]] {
                private var rowIndex = 0
                def hasNext: Boolean = rowIndex < 6
                def next: Iterator[Int] = {
                  // fix row index for inner iterator
                  val rowIdx = rowIndex
                  val rowIterator = new Iterator[Int] {
                    private var columnIndex = 0
                    def next: Int = {
                      // swap indices!!!
                      val p = array(rowIdx)(columnIndex)
                      columnIndex += 1
                      println("ColIndex = " + columnIndex.toString)
                      p
                    }
                    def hasNext: Boolean = columnIndex < 4
                  }
                  rowIndex += 1
                  println("RowIndex = " + rowIndex.toString)
                  rowIterator
                }
              }
            }
            for (row <- rows; elem <- row)
              println(elem)
          }
        

        但是

        val rows: Iterator[Iterator[Int]] = array.iterator.map(_.iterator)
        

        ziggystar 仍然更好,因为它也适用于非矩形二维数组,并且更简洁和“scalaish”。

        【讨论】:

          猜你喜欢
          • 2014-03-27
          • 2011-12-28
          • 2015-04-04
          • 2014-05-30
          • 2020-06-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-04-08
          相关资源
          最近更新 更多