2011-03-18 124 views
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] = { 
      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。

回答

5

下面的代碼如何?

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

它的工作原理,在REPL中進行了測試。雖然我不知道我是否實現了我所期望的「觀點」。歡迎任何評論。

編輯

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

array.iterator.map(_.iterator) 

這當然沒有「視圖」,沒有開銷。

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) 
ziggystar的

仍然是更好,因爲它與非矩形的二維陣列工作過,更consica和「scalaish」。

3

我不能從你的代碼中知道你真正想要做什麼。

如果你想用迭代的迭代器遍歷您的陣列中,有已經是一個簡單的方法來做到這一點:

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

如果你決定要一個迭代器,你也可以這樣做:

a2d.iterator.flatMap(_.iterator) 

如果你想遍歷即使數組是按行排序的,那麼你還有更多的工作要做(我認爲你正在嘗試做的事情,但是你混淆了你的數組指數,也許還有一些[R東西):

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