有人可以解释下面的代码吗?我发现它很难理解。如果有更好的解决方案,也请告诉我。
更新:我知道基本知识,如currying,模式匹配,List,map功能。但我不了解在flatMapSublists函数中使用两个泛型A和B的需要,' sublist @'。我认为,由于缺乏知识的点点滴滴,我无法理解整体解决方案。
查找nCr的所有值
// Example:
// scala> combinations(3, List('a, 'b, 'c, 'd, 'e, 'f))
// res0: List[List[Symbol]] = List(List('a, 'b, 'c), List('a, 'b, 'd), List('a, 'b, 'e), ...
解决方案:
// flatMapSublists is like list.flatMap, but instead of passing each element
// to the function, it passes successive sublists of L.
def flatMapSublists[A, B](ls: List[A])(f: (List[A]) => List[B]): List[B] =
ls match {
case Nil => Nil
case sublist @ (_ :: tail) => f(sublist) ::: flatMapSublists(tail)(f)
}
def ncr[A](n: Int, ls: List[A]): List[List[A]] =
if (n == 0) List(Nil)
else flatMapSublists(ls) { sl =>
ncr(n - 1, sl.tail) map { sl.head :: _ }
}
ncr(3, List('a, 'b, 'c, 'd, 'e, 'f))
输出:
List(List('a, 'b, 'c), List('a, 'b, 'd), List('a, 'b, 'e), List('a, 'b, 'f), List('a, 'c, 'd), List('a, 'c, 'e), List('a,'c, 'f), List('a, 'd, 'e), List('a, 'd, 'f), List('a, 'e, 'f), List('b, 'c,'d), List('b, 'c, 'e), List('b, 'c, 'f), List('b, 'd, 'e), List('b, 'd, 'f), List('b, 'e, 'f), List('c, 'd, 'e), List('c, 'd, 'f), List('c, 'e, 'f), List('d, 'e, 'f))
来源:http://aperiodic.net/phil/scala/s-99/p26.scala
非常感谢!
答案 0 :(得分:1)
关于通用类型用法:
acjay解释了在flatmap中使用泛型的一般原则。 为了给出一些关于如何确定多种类型与一种类型的需求的指示,让我们看一下这两种函数的输入和输出类型。
NCR: 输入:列表[A] 输出:列出[列表[A]]
flatmapLists: 输入: 列表[A] f:列表[A] =>列表[B]
输出: 列表[B]
如果我们将函数flatMapSublists的使用限制为函数f:它只支持List [A] =>列表[List [A]],我们可以将接口更改为仅使用一个泛型类型,它仍然可以工作。
def flatMapSublists[A](ls: List[A])(f: (List[A]) => List[List[A]]): List[List[A]] =
关于"子列表@"
当ls不是Nil时,子列表与ls相同,所以你不需要指定它,你可以直接使用ls。所以更新的函数如下所示:
def flatMapSublists[A](ls: List[A])(f: (List[A]) => List[List[A]]): List[List[A]] = {
ls match {
case Nil => Nil
case (_ :: tail) => {
f(ls) ::: flatMapSublists(tail)(f)
}
}
}
替代实施
遵循传统的递归方法(尽管不是尾递归)
def p26_ncr_recursive[A](n: Int, ls: List[A]): List[List[A]] = {
if (n==0) List(Nil)
else ls match {
case Nil => Nil
case head :: tail =>
p26_ncr_recursive(n - 1, tail).map {
head :: _
} ::: p26_ncr_recursive(n, tail)
}
}
答案 1 :(得分:0)
但我不了解在flatMapSublists函数中使用两个泛型A和B的需要,...
所有flatMap
和map
都有两个泛型,一个用于列表的类型,一个用于列出的类型。您可能不习惯在一个地方看到两者,因为标准库集合将这些集合定义为在预先存在的List
上具有一个类型参数的方法,该参数定义class
级别的其他类型参数。
'子列表@'
此语法仅将变量定义为整个匹配模式。当@的右侧不仅仅是一个简单的类型匹配,而是一个模式,并且你想要整个值时,可以使用它。您可能会认为@
是对左侧新val
的分配。
如果您有其他问题,请发表评论。逻辑是有点棘手的,所以我建议尝试为一个非常简单的案例ncr(3, List('a, 'b, 'c, 'd))
推理事物的流动。如果有帮助,您可以使用println
s来丢弃代码。