我刚开始在Scala和我的第一个项目,我正在写一个数独求解器。我遇到了一个很棒的网站,解释数独以及如何编写解算器:http://norvig.com/sudoku.html,我想从这个网站创建相应的Scala代码。
Sudoku网格的方块基本上是行名和列名的交叉乘积,这可以使用列表解析在Python中轻松生成:
# cross("AB", "12") = ["A1", "A2", "B1", "B2"]
def cross(A, B):
"Cross product of elements in A and elements in B."
return [a+b for a in A for b in B]
我花了一些时间思考如何在Scala中优雅地做到这一点,这就是我提出的:
// cross("AB", "12") => List[String]("A1", "A2", "B1", "B2")
def cross(r: String, c: String) = {
for(i <- r; j <- c) yield i + "" + j
}.toList
我很好奇是否有更好的方法在Scala中执行此操作?如果我可以执行yield i + j
,但由于某种原因会导致Int
,这似乎会更清晰。任何意见或建议将不胜感激。
答案 0 :(得分:1)
是的,Char
的添加是通过添加它们的整数等价物来定义的。我认为你的代码很好。你也可以使用字符串插值,并省略toList
(你将获得一个不可变的索引序列,而这很好):
def cross(r: String, c: String) = for(i <- r; j <- c) yield s"$i$j"
修改强>
IndexedSeq
至少与List
一样强大。只需检查您对结果的连续使用情况。它需要List
吗?例如。是否要使用head
和tail
以及模式匹配::
。如果没有,则没有理由要求您强制执行List
。如果您对输入参数使用map
和flatMap
而不是for
的语法糖,则可以使用collection.breakOut
参数直接映射到List
:
def cross(r: String, c: String): List[String] =
r.flatMap(i => c.map(j => s"$i$j"))(collection.breakOut)
不是很漂亮,但比额外toList
更快。