两个字符串的交叉产品

时间:2013-03-29 22:30:29

标签: scala

我刚开始在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,这似乎会更清晰。任何意见或建议将不胜感激。

1 个答案:

答案 0 :(得分:1)

是的,Char的添加是通过添加它们的整数等价物来定义的。我认为你的代码很好。你也可以使用字符串插值,并省略toList(你将获得一个不可变的索引序列,而这很好):

def cross(r: String, c: String) = for(i <- r; j <- c) yield s"$i$j"

修改

IndexedSeq至少与List一样强大。只需检查您对结果的连续使用情况。它需要List吗?例如。是否要使用headtail以及模式匹配::。如果没有,则没有理由要求您强制执行List。如果您对输入参数使用mapflatMap而不是for的语法糖,则可以使用collection.breakOut参数直接映射到List

def cross(r: String, c: String): List[String] = 
  r.flatMap(i => c.map(j => s"$i$j"))(collection.breakOut)

不是很漂亮,但比额外toList更快。