在 Scala 数独生成器中过滤嵌套列表和列表项
Filtering nested lists and list items in Scala sudoku generator
作为数独生成器的一部分,我有一个旨在过滤嵌套列表的函数,以便 return 仅 return 某些索引的内部列表和这些列表中某些索引的内部列表元素。这个想法是 return 一个 List[Int],其中包含取自 9x9 数独拼图的 3x3 正方形的值,表示为 List[List[Int]],它作为函数的参数提供。
我尝试了两种方法,但都无法始终如一地工作。一种方法尝试从列表中过滤掉某些子列表,然后从剩余列表中过滤掉项目。此函数完全适用于某些索引,但对于其他索引,它会从某些子列表中过滤掉太多或太少的索引值,但不是全部:
def getGroup(indexX: Int, indexY: Int, puzzle: List[List[Int]]): List[Int] = {
val groupX = { //determining row coordinate
if(indexX <= 2) 2
else if(indexX <= 5) 5
else 8
}
val groupY = { //determining column coordinate
if(indexY <= 2) 2
else if(indexY <= 5) 5
else 8
}
// Using filter
val subsection: List[List[Int]] = puzzle.filter(x => puzzle.indexOf(x) <= groupX && puzzle.indexOf(x) >= groupX - 2)
// This sometimes filters out too many or too few items
val group: List[List[Int]] = subsection.map(x => x.filter(y => x.indexOf(y) <= groupY && x.indexOf(y) >= groupY - 2))
val result = group.flatten
println("subsection " + subsection)
println("group " + group)
result
}
这是测试 List[List[Int]] 的一些输出,并打印以显示结果。我不清楚为什么不正确的索引会从某些子列表中过滤掉,但不是全部都在同一个函数调用中。我不认为我只是选择了错误的索引,否则对于同一函数调用中的所有子列表,它应该以相同的方式不正确。
test: List[List[Int]] = List(List(0, 2, 3, 4, 5, 6, 7, 8, 9), List(1, 2, 3, 4, 5, 6, 7, 8, 9), List(2, 2, 3, 4, 5, 6, 7, 8, 9), List(3, 2, 3, 4, 5, 6, 7, 8, 9), List(4, 2, 3, 4, 5, 6, 7, 8, 9), List(5, 2, 3, 4, 5, 6, 7, 8, 9), List(6, 2, 3, 4, 5, 6, 7, 8, 9), List(7, 2, 3, 4, 5, 6, 7, 8, 9), List(8, 2, 3, 4, 5, 6, 7, 8, 9))
scala> getGroup(2,2,test)
subsection: List(List(0, 2, 3, 4, 5, 6, 7, 8, 9), List(1, 2, 3, 4, 5, 6, 7, 8, 9), List(2, 2, 3, 4, 5, 6, 7, 8, 9))
group: List(List(0, 2, 3), List(1, 2, 3), List(2, 2, 3))
res12: List[Int] = List(0, 2, 3, 1, 2, 3, 2, 2, 3) //Correct
scala> getGroup(2,7,test)
subsection: List(List(0, 2, 3, 4, 5, 6, 7, 8, 9), List(1, 2, 3, 4, 5, 6, 7, 8, 9), List(2, 2, 3, 4, 5, 6, 7, 8, 9))
group: List(List(7, 8, 9), List(7, 8, 9), List(7, 8, 9))
res13: List[Int] = List(7, 8, 9, 7, 8, 9, 7, 8, 9) //Correct
scala> getGroup(7,7,test)
subsection: List(List(6, 2, 3, 4, 5, 6, 7, 8, 9), List(7, 2, 3, 4, 5, 6, 7, 8, 9), List(8, 2, 3, 4, 5, 6, 7, 8, 9))
group: List(List(7, 8, 9), List(8, 9), List(7, 9)) //Missing a 7 and an 8
res14: List[Int] = List(7, 8, 9, 8, 9, 7, 9)
scala> getGroup(4,0,test)
subsection: List(List(3, 2, 3, 4, 5, 6, 7, 8, 9), List(4, 2, 3, 4, 5, 6, 7, 8, 9), List(5, 2, 3, 4, 5, 6, 7, 8, 9))
group: List(List(3, 2, 3), List(4, 2, 3, 4), List(5, 2, 3, 5)) //Not enough values filtered out--unwanted 4 and 5
res32: List[Int] = List(3, 2, 3, 4, 2, 3, 4, 5, 2, 3, 5)
另一种方法使用 for 循环,它只会产生符合 if 条件的值:
def getGroup(indexX: Int, indexY: Int, puzzle: List[List[Int]]): List[Int] = {
//this portion is the same as above until the for expression:
val groupX = { //determining row coordinate
if(indexX <= 2) 2
else if(indexX <= 5) 5
else 8
}
val groupY = { //determining column coordinate
if(indexY <= 2) 2
else if(indexY <= 5) 5
else 8
}
// using for expression
val group = for(
outer <- puzzle if puzzle.indexOf(outer) <= groupX && puzzle.indexOf(outer) >= groupX - 2;
inner <- outer if outer.indexOf(inner) <= groupY && outer.indexOf(inner) >= groupY - 2)
yield inner
group
}
我已经用这个 List[List[Int]] 测试了这个函数,其中每个列表都以它的索引号开始,然后才向上计数:
val testGrid = List(List(0,2,3,4,5,6,7,8,9),List(1,2,3,4,5,6,7,8,9),List(2,2,3,4,5,6,7,8,9),
List(3,2,3,4,5,6,7,8,9),List(4,2,3,4,5,6,7,8,9),List(5,2,3,4,5,6,7,8,9),
List(6,2,3,4,5,6,7,8,9),List(7,2,3,4,5,6,7,8,9),List(8,2,3,4,5,6,7,8,9))
然而,输出并不总是正确的:
scala> getGroup(0, 0, testGrid)
res0: List[Int] = List(0, 2, 3, 1, 2, 3, 2, 2, 3) (correct)
scala> getGroup(3,3,testGrid)
res1: List[Int] = List(4, 5, 6, 5, 6, 4, 6) (too few)
scala> getGroup(3,7,testGrid)
res2: List[Int] = List(7, 8, 9, 7, 8, 9, 7, 8, 9) (correct)
scala> getGroup(7,7,testGrid)
res3: List[Int] = List(7, 8, 9, 8, 9, 7, 9) (too few)
scala> getGroup(7,0,testGrid)
res5: List[Int] = List(6, 2, 3, 6, 7, 2, 3, 7, 8, 2, 3, 8) (too many)
对于为什么我得到这个输出可能有一个明显的答案,但它已经逃脱了我。我怀疑它与内部循环有关,因为 indexY 小于 3 的所有测试都是正确的,无论 indexX 的值如何。
我将不胜感激任何对这些尝试的反馈。我也很感激任何关于可以使此功能更直观或简洁的替代方法的想法。
您可以使用 .slice
按索引过滤列表的一部分。然后 .map(x => x.slice(...))
对内部列表执行相同的操作,最后 .flatten
将 List[List[A]]
转换为 List[A]
。总计:
def getGroup(indexX: Int, indexY: Int, puzzle: List[List[Int]]): List[Int] = {
val xStart = indexX / 3 * 3
val yStart = indexY / 3 * 3
puzzle.slice(xStart, xStart + 3).map(row => row.slice(yStart, yStart + 3)).flatten
}
作为数独生成器的一部分,我有一个旨在过滤嵌套列表的函数,以便 return 仅 return 某些索引的内部列表和这些列表中某些索引的内部列表元素。这个想法是 return 一个 List[Int],其中包含取自 9x9 数独拼图的 3x3 正方形的值,表示为 List[List[Int]],它作为函数的参数提供。
我尝试了两种方法,但都无法始终如一地工作。一种方法尝试从列表中过滤掉某些子列表,然后从剩余列表中过滤掉项目。此函数完全适用于某些索引,但对于其他索引,它会从某些子列表中过滤掉太多或太少的索引值,但不是全部:
def getGroup(indexX: Int, indexY: Int, puzzle: List[List[Int]]): List[Int] = {
val groupX = { //determining row coordinate
if(indexX <= 2) 2
else if(indexX <= 5) 5
else 8
}
val groupY = { //determining column coordinate
if(indexY <= 2) 2
else if(indexY <= 5) 5
else 8
}
// Using filter
val subsection: List[List[Int]] = puzzle.filter(x => puzzle.indexOf(x) <= groupX && puzzle.indexOf(x) >= groupX - 2)
// This sometimes filters out too many or too few items
val group: List[List[Int]] = subsection.map(x => x.filter(y => x.indexOf(y) <= groupY && x.indexOf(y) >= groupY - 2))
val result = group.flatten
println("subsection " + subsection)
println("group " + group)
result
}
这是测试 List[List[Int]] 的一些输出,并打印以显示结果。我不清楚为什么不正确的索引会从某些子列表中过滤掉,但不是全部都在同一个函数调用中。我不认为我只是选择了错误的索引,否则对于同一函数调用中的所有子列表,它应该以相同的方式不正确。
test: List[List[Int]] = List(List(0, 2, 3, 4, 5, 6, 7, 8, 9), List(1, 2, 3, 4, 5, 6, 7, 8, 9), List(2, 2, 3, 4, 5, 6, 7, 8, 9), List(3, 2, 3, 4, 5, 6, 7, 8, 9), List(4, 2, 3, 4, 5, 6, 7, 8, 9), List(5, 2, 3, 4, 5, 6, 7, 8, 9), List(6, 2, 3, 4, 5, 6, 7, 8, 9), List(7, 2, 3, 4, 5, 6, 7, 8, 9), List(8, 2, 3, 4, 5, 6, 7, 8, 9))
scala> getGroup(2,2,test)
subsection: List(List(0, 2, 3, 4, 5, 6, 7, 8, 9), List(1, 2, 3, 4, 5, 6, 7, 8, 9), List(2, 2, 3, 4, 5, 6, 7, 8, 9))
group: List(List(0, 2, 3), List(1, 2, 3), List(2, 2, 3))
res12: List[Int] = List(0, 2, 3, 1, 2, 3, 2, 2, 3) //Correct
scala> getGroup(2,7,test)
subsection: List(List(0, 2, 3, 4, 5, 6, 7, 8, 9), List(1, 2, 3, 4, 5, 6, 7, 8, 9), List(2, 2, 3, 4, 5, 6, 7, 8, 9))
group: List(List(7, 8, 9), List(7, 8, 9), List(7, 8, 9))
res13: List[Int] = List(7, 8, 9, 7, 8, 9, 7, 8, 9) //Correct
scala> getGroup(7,7,test)
subsection: List(List(6, 2, 3, 4, 5, 6, 7, 8, 9), List(7, 2, 3, 4, 5, 6, 7, 8, 9), List(8, 2, 3, 4, 5, 6, 7, 8, 9))
group: List(List(7, 8, 9), List(8, 9), List(7, 9)) //Missing a 7 and an 8
res14: List[Int] = List(7, 8, 9, 8, 9, 7, 9)
scala> getGroup(4,0,test)
subsection: List(List(3, 2, 3, 4, 5, 6, 7, 8, 9), List(4, 2, 3, 4, 5, 6, 7, 8, 9), List(5, 2, 3, 4, 5, 6, 7, 8, 9))
group: List(List(3, 2, 3), List(4, 2, 3, 4), List(5, 2, 3, 5)) //Not enough values filtered out--unwanted 4 and 5
res32: List[Int] = List(3, 2, 3, 4, 2, 3, 4, 5, 2, 3, 5)
另一种方法使用 for 循环,它只会产生符合 if 条件的值:
def getGroup(indexX: Int, indexY: Int, puzzle: List[List[Int]]): List[Int] = {
//this portion is the same as above until the for expression:
val groupX = { //determining row coordinate
if(indexX <= 2) 2
else if(indexX <= 5) 5
else 8
}
val groupY = { //determining column coordinate
if(indexY <= 2) 2
else if(indexY <= 5) 5
else 8
}
// using for expression
val group = for(
outer <- puzzle if puzzle.indexOf(outer) <= groupX && puzzle.indexOf(outer) >= groupX - 2;
inner <- outer if outer.indexOf(inner) <= groupY && outer.indexOf(inner) >= groupY - 2)
yield inner
group
}
我已经用这个 List[List[Int]] 测试了这个函数,其中每个列表都以它的索引号开始,然后才向上计数:
val testGrid = List(List(0,2,3,4,5,6,7,8,9),List(1,2,3,4,5,6,7,8,9),List(2,2,3,4,5,6,7,8,9),
List(3,2,3,4,5,6,7,8,9),List(4,2,3,4,5,6,7,8,9),List(5,2,3,4,5,6,7,8,9),
List(6,2,3,4,5,6,7,8,9),List(7,2,3,4,5,6,7,8,9),List(8,2,3,4,5,6,7,8,9))
然而,输出并不总是正确的:
scala> getGroup(0, 0, testGrid)
res0: List[Int] = List(0, 2, 3, 1, 2, 3, 2, 2, 3) (correct)
scala> getGroup(3,3,testGrid)
res1: List[Int] = List(4, 5, 6, 5, 6, 4, 6) (too few)
scala> getGroup(3,7,testGrid)
res2: List[Int] = List(7, 8, 9, 7, 8, 9, 7, 8, 9) (correct)
scala> getGroup(7,7,testGrid)
res3: List[Int] = List(7, 8, 9, 8, 9, 7, 9) (too few)
scala> getGroup(7,0,testGrid)
res5: List[Int] = List(6, 2, 3, 6, 7, 2, 3, 7, 8, 2, 3, 8) (too many)
对于为什么我得到这个输出可能有一个明显的答案,但它已经逃脱了我。我怀疑它与内部循环有关,因为 indexY 小于 3 的所有测试都是正确的,无论 indexX 的值如何。
我将不胜感激任何对这些尝试的反馈。我也很感激任何关于可以使此功能更直观或简洁的替代方法的想法。
您可以使用 .slice
按索引过滤列表的一部分。然后 .map(x => x.slice(...))
对内部列表执行相同的操作,最后 .flatten
将 List[List[A]]
转换为 List[A]
。总计:
def getGroup(indexX: Int, indexY: Int, puzzle: List[List[Int]]): List[Int] = {
val xStart = indexX / 3 * 3
val yStart = indexY / 3 * 3
puzzle.slice(xStart, xStart + 3).map(row => row.slice(yStart, yStart + 3)).flatten
}