为二维数组编写一个迭代器

4
我正在尝试为一个二维数组编写迭代器。以下是我想出的代码。
  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。你能帮我找出问题出在哪里吗?
谢谢, Siddharth Raina.
3个回答

5
以下代码怎么样?
val array = Array(Array(1,2,3),Array(4,5,6),Array(7,8,9))
array.view.flatten.iterator

经过REPL测试,它可以工作。虽然我不知道我是否实现了我打算使用“view”的目标。欢迎任何评论。

编辑

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

array.iterator.map(_.iterator)

这样做不需要“视图”且没有额外的开销。


4
我可以看出你的代码想要做什么。
如果你想使用迭代器来遍历你的数组,那已经有一种简单的方法可以实现:
val a2d = Array.tabulate(4,4)((i,j)=>4*i+j)
a2d.iterator.map(_.iterator)

如果您决定只使用一个迭代器,也可以这样做:

a2d.iterator.flatMap(_.iterator)

如果你想在行主序下遍历列,那么你需要做更多的工作(我认为这就是你想要做的事情,但你混淆了数组索引,可能还有其他的一些东西):

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中它似乎不像您希望的那样工作。


1

如果你想以命令式风格手工完成它:

  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)

of ziggystar 仍然更好,因为它可以与非矩形2D数组一起使用,并且更简洁和“scalaish”。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接