我必须编写一个方法“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())
答案 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)操作。