Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

2d scala array iteration

Tags:

arrays

scala

I have a 2d array of type boolean (not important) It is easy to iterate over the array in non-functional style. How to do it FP style?

var matrix = Array.ofDim[Boolean](5, 5) 

for ex, I would like to iterate through all the rows for a given column and return a list of int that would match a specific function. Example: for column 3, iterate through rows 1 to 5 to return 4, 5 if the cell at (4, 3), (5, 3) match a specif function. Thx v much

def getChildren(nodeId: Int) : List[Int] = {
    info("getChildren("+nodeId+")")

    var list = List[Int]()
    val nodeIndex = id2indexMap(nodeId)

    for (rowIndex <- 0 until matrix.size) {
      val elem = matrix(rowIndex)(nodeIndex)
      if (elem) {
        println("Row Index = " + rowIndex)
        list = rowIndex :: list
      }
    }

    list
  }
like image 945
jts Avatar asked Sep 12 '11 10:09

jts


2 Answers

What about

(1 to 5) filter {i => predicate(matrix(i)(3))}

where predicate is your function?

Note that initialized with (5,5) indexes goes from 0 to 4.

Update: based on your example

def getChildren(nodeId: Int) : List[Int] = {
  info("getChildren("+nodeId+")")
  val nodeIndex = id2indexMap(nodeId)

  val result = (0  until matrix.size).filter(matrix(_)(nodeIndex)).toList
  result.forEach(println)
  result
}

You may move the print in the fiter if you want too, and reverse the list if you want it exactly as in your example

like image 168
Didier Dupont Avatar answered Oct 01 '22 15:10

Didier Dupont


If you're not comfortable with filters and zips, you can stick with the for-comprehension but use it in a more functional way:

for {
  rowIndex <- matrix.indices
  if matrix(rowIndex)(nodeIndex)
} yield { 
  println("Row Index = " + rowIndex)
  rowIndex
}

yield builds a new collection from the results of the for-comprehension, so this expression evaluates to the collection you want to return. seq.indices is a method equivalent to 0 until seq.size. The curly braces allow you to span multiple lines without semicolons, but you can make it in-line if you want:

for (rowIndex <- matrix.indices; if matrix(rowIndex)(nodeIndex)) yield rowIndex

Should probably also mention that normally if you're iterating through an Array you won't need to refer to the indices at all. You'd do something like

for {
  row  <- matrix 
  elem <- row
} yield f(elem)

but your use-case is a bit unusual in that it requires the indices of the elements, which you shouldn't normally be concerned with (using array indices is essentially a quick and dirty hack to pair a data element with a number). If you want to capture and use the notion of position you might be better off using a Map[Int, Boolean] or a case class with such a field.

like image 40
Luigi Plinge Avatar answered Oct 01 '22 14:10

Luigi Plinge