在 scala 中递归构建列表的挑战
Posted
技术标签:
【中文标题】在 scala 中递归构建列表的挑战【英文标题】:Challenge in building a list in scala recursively 【发布时间】:2016-05-14 16:47:05 【问题描述】:如何编写一个函数,该函数构建一个给定长度的列表。通过将 f 应用于元素的索引来确定每个元素:
def buildList[A](length: Int, f: Int => A): List[A]
测试用例是这样的:
test("test")
def f(x: Int) = x
assert(buildList(10, f) == List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9))
所以输入示例是 listBuild(10,f) = output List(0,....9)
我知道如何在 OOL 中做到这一点,但功能性编程对我来说是一个新概念。
关于如何做到这一点的任何想法?至少,伪代码会有所帮助..
PS:这不是硬件。我一直在尝试自学 scala,这是我一直在努力解决的功能......
【问题讨论】:
I have been trying to teach myself scala and this is a function I have been struggling with...
继续 - 我记得 2 年前学习折叠时我的头撞到了墙上
"这不是硬件。"如果您这么说,但奇怪的是(至少)你们中的两个人今天就同一功能提出了问题:***.com/questions/35204312/…
List.tabulate(length)(f)
正是您想要的。但我明白重点是自己写
【参考方案1】:
这里最好不要使用递归。您可以使用Range 获取包含索引的序列。将函数应用于集合的每个元素称为 map。将两者结合起来可以得到:
0 until length map f
【讨论】:
"It's preferable not to use recursion here."
我认为,解释为什么不应该明确使用“递归”也是可取的。
这是一个可读性和惯用的函数式编程风格的问题。递归仅在其他方法不可行或不太清晰时使用。
当然,卡尔。在我看来,在有人学习函数式编程的构建块的情况下,直接跳到更高阶的函数(如until
)并没有帮助。我认为最好实现非尾递归解决方案。然后,编写尾递归解,然后使用fold
。最后,尽可能完全跳过fold
——只使用高阶函数,例如filter
、sum
等。
until
不是高阶函数。 sum
也不是。 map
和 filter
是。 en.wikipedia.org/wiki/Higher-order_function
就个人而言,@Kevin,我认为函数式编程通常很难学习,因为最复杂的主题往往是先教的。 使用 像map
这样的高阶函数比递归更容易理解。如果您在谈论 实施 map
那将是另一回事。【参考方案2】:
scala> def buildHelper(x: Int): List[Int] =
| if (x < 0) List() else x :: buildHelper(x-1)
buildHelper: (x: Int)List[Int]
scala> def buildList(x: Int): List[Int] =
| ???
buildList: (x: Int)List[Int]
buildList
的实现(滚动查看它 - 但我会尝试自己先实现它):
buildHelper(x).reverse
scala> buildList(10)
res2: List[Int] = List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
【讨论】:
这里不使用函数f
。【参考方案3】:
在 Scala 中递归构建列表
你可以试试这样的:
object UtilList
def build[A](length: Int, f: Int => A): List[A] =
val list: List[A]= List()
@annotation.tailrec
def foo(list: List[A], index: Int, f: Int => A): List[A] =
if (index == length) list
else foo(f(index) :: list, index + 1, f)
foo(list, 0, f)
【讨论】:
【参考方案4】:-
k 是一个整数,永远不会匹配空列表 Nil。
这是你的函数,使用“buildLister”
def listBuilder[A](k:Int, f:Int=>A) : List[A] = 如果(k
def buildLister[A](k:Int, f:Int=>A) : List[A] = listBuilder(k-1, f).reverse
【讨论】:
@user_456059239,为了获得准确的行为,只需反转列表(已编辑)【参考方案5】:我认为这是最简单优雅的递归列表生成:
def listBuilder(iterate : Int): List[Int] =
if(iterate == 0) List() :+ 0
else listBuilder(iterate-1) :+ iterate
【讨论】:
以上是关于在 scala 中递归构建列表的挑战的主要内容,如果未能解决你的问题,请参考以下文章
scala中的特别函数递归地连接两个列表:不使用“concat”