在 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——只使用高阶函数,例如filtersum等。 until 不是高阶函数。 sum 也不是。 mapfilter 是。 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”

scala-尾递归

使用简单递归从未排序列表中构建二叉搜索树

从示例逐渐理解Scala尾递归

如何使用append / 3以递归方式在prolog中构建列表?

Scala尾递归优化