访问Scala中特定单元格的索引

时间:2013-12-05 02:02:06

标签: scala collections

我必须编写一个方法“all()”,它返回一个元组列表;当函数在列表中遇到0时,每个元组将包含与特定给定行和列相关的行,列和集合。我已经编写了“hyp”函数,它返回我需要的设置部分,例如:Set(1,2)。我正在使用列表列表:

 | 0 | 0 | 9 |
 | 0 | x | 0 |
 | 7 | 0 | 8 |

如果Set(1,2)指的是标记为x的单元格,则all()应返回:(1,1,Set(1,2))其中1,1是行和列的索引。 我使用zipWithIndex编写了这个方法。在没有zipWithIndex的情况下,有没有更简单的方法来访问索引?提前致谢 代码:

 def all(): List[(Int, Int, Set[Int])] = 
 {
  puzzle.list.zipWithIndex flatMap 
  { 
    rowAndIndex =>
    rowAndIndex._1.zipWithIndex.withFilter(_._1 == 0) map 
    { 
      colAndIndex =>
      (rowAndIndex._2, colAndIndex._2,  hyp(rowAndIndex._2, colAndIndex._2)) 
    }
  }
 }  

(_._ 1 == 0)是因为函数只有在网格中找到0时才返回(Int,Int,Set())

2 个答案:

答案 0 :(得分:1)

使用zipWithIndex是相当常见的。可以通过元组中的模式匹配变量来最小化与元组/对的摔跤:

def all(grid: List[List[Int]]): List[(Int, Int, Set[Int])] =
  grid.zipWithIndex flatMap {case (row, r) =>
    row.zipWithIndex.withFilter(_._1 == 0) map {case (col, c) => (r, c,  hyp(r, c))}
  }

可以转换为100%等效的理解:

def all(grid: List[List[Int]]): List[(Int, Int, Set[Int])] =
  for {(row, r) <- grid.zipWithIndex; 
       (col, c) <- row.zipWithIndex if (col == 0)} yield (r, c,  hyp(r, c))       

以上两者都产生相同的编译代码。

请注意,您的要求意味着所有解决方案都是最小的O(n)= O(r * c) - 您必须访问每个单元格。然而,user60561的答案的整体行为是O(n ^ 2)= O((r * c)^ 2):对于每个单元格,在列表(x)(y)中有一个O(n)查找:

for{ x <- list.indices
     y <- list(0).indices
     if list(x)(y) == 0 } yield (x, y, hyp(x, y))

这是类似的(命令性的!)逻辑,但O(n):

var r, c = -1
for{ row <- list; col <- row if col == 0} yield {
  r += 1
  c += 1
  (r, c, hyp(r, c))
}

递归版本(使用结果累加器启用尾递归):

type Grid = List[List[Int]]
type GridHyp = List[(Int, Int, Set[Int])]

def all(grid: Grid): GridHyp = {
  def rowHypIter(row: List[Int], r: Int, c: Int, accum: GridHyp) = row match {
    case Nil => accum
    case col :: othCols => rowHypIter(othCols, r, c + 1, hyp(r, c) :: accum)}
  def gridHypIter(grid: Grid, r: Int, accum: GridHyp) = grid match {
    case Nil => accum
    case row :: othRows => gridHypIter(othRows, r + 1, rowHyp(row, r, 0, accum))}
  gridHypIter(grid, 0, Nil)
}

'Monadic'逻辑(flatmap / map / withFilter或等效for-comprehensions)通常/通常比递归+模式匹配更整洁 - 这里很明显。

答案 1 :(得分:0)

我能想到的最简单的方法就是循环经典:

for{ x <- list.indices
     y <- list(0).indices
     if list(x)(y) == 0 } yield (x, y, hyp(x, y))

它假设您的第二个维度是统一的大小。使用此代码,如果您的网格大小大于100,我还建议您使用数组或向量,因为list(x)(y)是O(n)操作。