我正在研究课程的最后一个项目" scala"中的函数式编程。我需要实现一个名为组合的函数,它接受一个字符出现列表并输出所有可能的字符出现子集。例如,出现列表List(('a', 2), ('b', 2))
的子集是:
List(
List(),
List(('a', 1)),
List(('a', 2)),
List(('b', 1)),
List(('a', 1), ('b', 1)),
List(('a', 2), ('b', 1)),
List(('b', 2)),
List(('a', 1), ('b', 2)),
List(('a', 2), ('b', 2))
)
我解决这个问题的方法是遍历每个字符(例如' a'),并获取其可能的出现次数(从0到2),并将其预备到当前子集。然后继续下一个字符并重复,直到我到达列表的末尾,这是由基本案例捕获的。我用以下的理解实现了这个:
type Occurrences = List[(Char, Int)]
def combinations(occurrences: Occurrences): List[Occurrences] =
if (occurrences == List()) List() // base case
else
for {
(c, n) <- occurrences
subc <- combinations((occurrences.toMap - c).toList)
i <- 0 to n
} yield {
if (i == 0) subc // not including c in the subset
else (c, i) :: subc // including c in the subset
}
当我拨打combinations(List(('a', 2), ('b', 2))
时,此功能总是给我一个空列表。任何想法为什么会这样?
答案 0 :(得分:1)
意外输出的原因在于:
subc <- combinations((occurrences.toMap - c).toList)
这将递归,加载堆栈帧,直到最终返回基本案例List()
。现在,请记住,在for
理解中,生成器(<-
)是通过map
或flatMap
实现的,一旦您映射到空集合,您就完成了。< / p>
List[Int]().map(_ + 1).foreach(_ => println("got it")) // no output
因此,未调用以下生成器i <- 0 to n
,yield
没有任何内容,空List()
是唯一返回的内容。然后堆栈框架弹出,接收到空的List()
等
答案 1 :(得分:0)
问题在于:
subc <- combinations((occurrences.toMap - c).toList)
在基本案例正上方的调用中,这被评估为List()
,这会妨碍你的理解:
scala> for {a <- 0 to 3; b <- List()} yield a
res0: scala.collection.immutable.IndexedSeq[Int] = Vector()
这使得该调用返回List()
等等,这意味着您将在调用堆栈中一直返回空列表,这就是您在顶部获得List()
的原因。