I am trying to write an iterator for a 2D array. The following is what I have come 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 when run skips the first row, and also gives an ArrayIndexOutOfBoundsException
when all elements have been printed. Can you help me figure out where I've gone wrong?
Thank you,
Siddharth Raina.
How 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 tested in REPL. Though I don't know if I achieve what I intended with "view". Any comments are welcome.
Edit
I forgot the author wanted a nested iterator.
array.iterator.map(_.iterator)
This certainly works without the "view" and without overhead.
I can't tell from your code what you actually want to do.
If you want traverse your array with iterators of iterators, there's already an easy way to do it:
val a2d = Array.tabulate(4,4)((i,j)=>4*i+j)
a2d.iterator.map(_.iterator)
And if you decide you want a single iterator, you can do that too:
a2d.iterator.flatMap(_.iterator)
If you want to traverse columns even though the array is in row-major order, then you have a little more work to do (which I think is what you were trying to do, but you mixed up your array indices, and maybe some other things):
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)
}
}
}
}
Now you can
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
(You also ought to be able to do a2d.view.transpose.iterator.map(_.iterator)
to avoid making a copy, but unfortunately it doesn't look like this works the way you'd hope in 2.8.1.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With