我想在scala中实现一个组合函数,我的代码如下:
def combination[A](n: Int, ls: List[A]): List[List[A]] ={
(n, ls) match{
case (_, Nil) => List(Nil)
case (1, _) => ls.map(List(_))
case (_, _) if n > ls.size => List.empty
case _ => ls.flatMap(x => combination(n - 1, subList(x, ls)).map(x :: _))
}
}
def subList[A](e: A, in: List[A]) = in.takeRight(in.size - in.indexOf(e) - 1)
但结果不是我的预期。当我拨打combination(3, List('a, 'b, 'c, 'd, 'e, 'f)
时。它会给我一些或两个元素的结果,如List('d,'f),List('f)等等。任何人都可以帮我找到问题吗?感谢。
更新: 正确的版本是
def combination[A](n: Int, ls: List[A]): List[List[A]] ={
(n, ls) match{
case (_, Nil) => Nil
case (1, _) => ls.map(List(_))
case (_, _) if n > ls.size => Nil
case _ => ls.flatMap(x => combination(n - 1, subList(x, ls)).map(x :: _))
}
}
def subList[A](e: A, in: List[A]) = in.takeRight(in.size - in.indexOf(e) - 1)
答案 0 :(得分:2)
案件太多,不必要的复杂combinations2
和subList
。
回想一下如何定义combinations。如果你有一组{a1, ..., aN}
,并且想要从这个集合中选择k
个元素,那么你基本上可以只做两个的事情:
a1
包含在子集中。然后,您必须从剩余的k
。{a2, ..., aN}
个元素
a1
包含在子集中。然后,您必须从k-1
中选择{a2, ..., aN}
个元素,并将a0
添加到这些k-1
元素中。那就是公式
C(N, k) = C(N - 1, k) + C(N - 1, k - 1)
来自。
翻译成代码,这只是:
def comb[A](ls: List[A], k: Int): List[List[A]] = {
if (k == 0) List(Nil)
else ls match {
case Nil => List()
case h :: t => comb(t, k) ++ comb(t, k - 1).map(h :: _)
}
}
示例:
comb(List('a, 'b, 'c, 'd, 'e), 3) foreach println
给出:
List('c, 'd, 'e)
List('b, 'd, 'e)
List('b, 'c, 'e)
List('b, 'c, 'd)
List('a, 'd, 'e)
List('a, 'c, 'e)
List('a, 'c, 'd)
List('a, 'b, 'e)
List('a, 'b, 'd)
List('a, 'b, 'c)
答案 1 :(得分:0)
在最后一种情况下,您正在呼叫combination2
。如果您更改为combination
(subList
的合理定义),则可以使用。我想这是中间版本的一部分。
答案 2 :(得分:0)
这是一种更简单的方法
def comb[A](n: Int, ls:List[A]): List[List[A]] = {
if(ls.isEmpty) List(Nil)
else ls.toSet[A].subsets.map(_.toList).filter(_.length == n).toList
}