Scala my combinations函数返回一个空列表

Scala my combinations函数返回一个空列表,scala,functional-programming,Scala,Functional Programming,我正在研究第26个问题,已经被困在第26个问题上了。 生成从列表的N个元素中选择的K个不同对象的组合。 在浪费了几个小时之后,我决定看看用Haskell编写的解决方案: combinations :: Int -> [a] -> [[a]] combinations 0 _ = [ [] ] combinations n xs = [ y:ys | y:xs' <- tails xs , ys <- combinations

我正在研究第26个问题,已经被困在第26个问题上了。 生成从列表的N个元素中选择的K个不同对象的组合。 在浪费了几个小时之后,我决定看看用Haskell编写的解决方案:

combinations :: Int -> [a] -> [[a]]
combinations 0 _  = [ [] ]
combinations n xs = [ y:ys | y:xs' <- tails xs
                       , ys <- combinations (n-1) xs']
但是,我的组合返回一个空列表。有什么想法吗? 我们也非常欢迎其他有解释的解决方案。谢谢

编辑:问题的描述

生成从列表的N个元素中选择的K个不同对象的组合。 一个由3人组成的委员会可以从12人组成的小组中通过多少种方式选出?我们都知道有C(12,3)=220种可能性(C(N,K)表示众所周知的二项式系数)。对于纯粹的数学家来说,这个结果可能是伟大的。但我们想真正创造所有的可能性

例如: scala>组合(3,列表('a,'b,'c,'d,'e,'f)) res0:List[List[Symbol]=List(List('a,'b,'c),List('a,'b,'d),List('a,'b,'e)


您的问题是使用
for
理解列表。如果
for
检测到一个空列表,则它会短路并返回一个空列表,而不是“cons”您的head元素。以下是一个示例:

scala> for { xs <- List() } yield println("It worked!") // This never prints
res0: List[Unit] = List()
scala>用于{xs List[List[T]]()
案例(n,xs)=>{
val tails=allTails(xs)。反向
println(尾部)
为了{

y::xss还有一种解决方法

def combinations[T](n: Int, ls: List[T]): List[List[T]] = {
var ms: List[List[T]] = List[List[T]]();
val len = ls.size
if (n > len)
  throw new Error();
else if (n == len)
  List(ls)
else if (n == 1)
  ls map (a => List(a))
else {
  for (i <- n to len) {
    val take: List[T] = ls take i;
    val temp = combinations(n - 1, take.init) map (a => take.last :: a)
    ms = ms ::: temp
  }
  ms
}
}
def组合[T](n:Int,ls:List[T]):List[List[T]={
var-ms:List[List[T]]=List[List[T]]();
val len=ls.size
如果(n>len)
抛出新错误();
else if(n==len)
列表(ls)
else如果(n==1)
ls映射(a=>列表(a))
否则{
for(我取最后一个::a)
ms=ms:::温度
}
太太
}
}

所以组合(2,List(1,2,3))给出:
List[List[Int]]=List(List(2,1),List(3,1),List(3,2))

正如Noah所指出的,我的问题是,
的空列表不会产生。然而,Noah建议的黑客解决方法是错误的。它会在每个递归步骤的结果中添加一个空列表。无论如何,这是我的最终解决方案。我将基本情况更改为“case(1,xs)”(n匹配1)

def组合[T](n:Int,ls:List[T]):List[List[T]=(n,ls)匹配{
case(1,xs)=>xs.map(List(u2;))
案例(n,xs)=>{
val tails=allTails(xs)。反向
为了{

y::xss在此处翻译Haskell版本时出错:

case (0, _) => List[List[T]]()
这将返回一个空列表

combinations 0 _  = [ [] ]
返回一个包含单个元素的列表,该元素为空列表

这本质上是说,有一种方法可以选择零项,这一点很重要,因为对于我们选择更多项的情况,代码是在这种情况下递归构建的。如果没有方法选择零项,那么也就没有方法选择一项,依此类推。这就是代码中发生的情况

如果将Scala版本修复为与Haskell版本相同:

case (0, _) => List(List[T]())

它工作正常。

谢谢。现在它返回了一些东西。但是结果不正确。真不敢相信以前没有人发现。非常感谢!@EntryLevelDev:我在Haskell中编写类似代码时也犯了同样的错误,所以在阅读了标题后,这是我首先要寻找的。
def combinations[T](n: Int, ls: List[T]): List[List[T]] = (n, ls) match {
case (1, xs) =>  xs.map(List(_))
case (n, xs) => {
  val tails = allTails(xs).reverse
  for {
    y :: xss <- allTails(xs).reverse
    ys <- combinations((n - 1), xss)
  } yield y :: ys
}
}
//combinations(3, List(1, 2, 3, 4))
//List(List(1, 2, 3), List(1, 2, 4), List(1, 3, 4), List(2, 3, 4))
//combinations(2, List(0, 1, 2, 3))
//List(List(0, 1), List(0, 2), List(0, 3), List(1, 2), List(1, 3), List(2, 3))

def allTails[T](ls: List[T]): List[List[T]] = {
ls./:(0, List[List[T]]())((acc, c) => {
  (acc._1 + 1, ls.drop(acc._1) :: acc._2)
})._2
}
//allTails(List(0,1,2,3)) 
//List(List(3), List(2, 3), List(1, 2, 3), List(0, 1, 2, 3))
case (0, _) => List[List[T]]()
combinations 0 _  = [ [] ]
case (0, _) => List(List[T]())