Writing an iterator for a 2D array

I am trying to write an iterator for a 2D array. The following is what I came up with.

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

The above code at startup skips the first line, and also gives ArrayIndexOutOfBoundsExceptionwhen all the elements have been printed. Can you help me figure out where I made a mistake?

Thanks,
Siddhart Raina.

+3
source share
3 answers

What about the following code?

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

It works as verified in REPL. Although I do not know if I have achieved what I intended with a “look”. Any comments are welcome.

Edit

I forgot that the author needs a nested iterator.

array.iterator.map(_.iterator)

This certainly works without “presentation” and without overhead.

+5
source

, .

, :

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

+3

If you want to do it manually in an imperative style:

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

but

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

ziggystar is even better, because its work with non-rectangular 2D arrays is also more specific and "scalaish".

+1
source

All Articles