2D Scala数组迭代

6

我有一个类型为布尔值的二维数组(不重要)。 以非函数式的方式迭代该数组很容易。 如何以函数式风格实现呢?

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

例如,我想迭代给定列的所有行,并返回与特定函数匹配的整数列表。 示例:对于第3列,迭代行1到5以返回4、5,如果单元格(4,3)、(5,3)与特定函数匹配。非常感谢。

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
  }
3个回答

4

关于什么?

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

其中predicate是您的函数?

请注意,初始化为(5,5)索引从0到4。

更新: 根据您的示例

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
}

你可以移动过滤器中的打印内容,如果想要,也可以反转列表,使其与你的示例完全一致。

我认为如果初始结构是一个二维数组,你的解决方案将返回一个数组? - jts
啊,另一个区别是我在考虑直接在二维数组上进行过滤,但这样做会丢失行索引:val children = matrix.filter(row => row(nodeIndex)),它返回2个1D数组 - 但我不知道哪一个。 - jts
不是很准确,我过滤的结构是一个范围(Range),而不是数组(因为你想要输出的是索引)。结果类型是IndexedSeq[Int],恰好是一个向量(Vector)。如果你想要一个列表(List),只需使用.toList即可,但是向量(Vector)通常比列表更好。 - Didier Dupont
这是我想要实现的非FP版本(编辑主文件) - jts

2

如果您不熟悉过滤器和zip操作,您可以继续使用for-comprehension,但以更加函数化的方式使用:

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

yield 从 for-comprehension 的结果构建一个新的集合,因此该表达式评估为您要返回的集合。 seq.indices 是一个等效于 0 until seq.size 的方法。花括号允许您跨越多行而不需要分号,但如果您想要,也可以将其设置为内联:

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

可能还需要提到的是,通常情况下,如果您正在遍历一个数组,您不需要引用索引。您可以这样做:

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

但是您的用例有些不寻常,因为它需要元素的索引,而您通常不应该关心它们(使用数组索引本质上是一种快速而肮脏的方法,可以将数据元素与数字配对)。如果您想捕捉和使用位置的概念,最好使用 Map[Int, Boolean] 或带有此类字段的 case class


1
def findIndices[A](aa: Array[Array[A]], pred: A => Boolean): Array[Array[Int]] =
  aa.map(row => 
    row.zipWithIndex.collect{ 
      case (v,i) if pred(v) => i 
  }
)

你可以通过提取仅在单行中查找索引的函数来重构它,使其更加优美:

def findIndices2[A](xs: Array[A], pred: A => Boolean): Array[Int] =
  xs.zipWithIndex.collect{ 
    case (v,i) if pred(v) => i 
  }

然后写

matrix.map(row  => findIndices2(row, pred))

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