【问题标题】:Scala case matching using inductive structure failing while mapping a list映射列表时使用归纳结构的Scala案例匹配失败
【发布时间】:2021-01-07 09:37:51
【问题描述】:

在这里,我试图实现以下目标:

  1. 使用递归,返回一个新列表,该列表由列表 l 的所有元素组成,当对它们调用函数 f 时返回 true。

  2. 返回的列表元素必须保持与原始列表相同的顺序。

编辑:

到目前为止,我已经能够消除类型不匹配错误。我在给定定义的情况下遍历列表并返回新列表的目标似乎还很遥远。

sealed trait NumList
case object Nil extends NumList
case class Cons(n: Int, l: NumList) extends NumList

def filterNumList(l: NumList, f: Int => Boolean): NumList = {
    l match {
            case Nil => Nil
            case Cons(i, Nil) => Cons(i, Nil)
            case Cons(i, Cons(j, Nil)) if f(i) == false => filterNumList(Cons(j, Nil),f)
            case Cons(i, Cons(j, Nil)) if f(i) == true => filterNumList(Cons(i, Nil),f)
            case Cons(i, rest) if f(i) == true => filterNumList(Cons(i,rest),f)
            case Cons(i, Cons(j, rest)) if f(i) == false => filterNumList(Cons(j, rest),f)
        }
}

val l1 = Cons(12, Cons(25, Cons(37, Nil)))
def f1(j: Int): Boolean =  j <= 25 && j >= 12
println(filterNumList(l1, f1))

【问题讨论】:

  • 您的代码无法编译。您应该首先修复编译错误。
  • e 未定义,f == truef == false 没有意义。
  • @DmytroMitin 我已经更正了 e。如果函数 f 返回 true,我想将该元素放入新列表并继续测试列表的其余部分。我不确定逻辑在哪里不正确。
  • f == truef == false 仍然没有意义。 f 是一个函数,你不应该将它与布尔值进行比较。
  • @DmytroMitin 我明白了,我认为这是正确的,因为返回值是从生成布尔值的测试用例派生的布尔值。哦!我应该加了参数i吧?

标签: scala recursion filter pattern-matching


【解决方案1】:

您必须探索的案例比您所提出的要简单。

你感兴趣的是:

  1. 列表为空:
    • 这里什么都不做,只返回空列表
  2. 列表的第一项满足谓词:
    • 构建一个列表
      • 包含第一项
      • 随后将过滤器应用于列表的其余部分
  3. 第一项满足谓词:
    • 只需将应用过滤器的结果返回到列表的其余部分

在伪代码中,这将是:

function filter(list, predicate)
  if empty(list)
    return the empty list
  else
    if predicate(head(list)) is true
      cons(head(list), filter(tail(list), predicate))
    else
      filter(tail(list), predicate)

在 Scala 中,这应该满足您的要求:

sealed trait NumList
case object Nil extends NumList
case class Cons(n: Int, l: NumList) extends NumList

def filterNumList(l: NumList, f: Int => Boolean): NumList = {
  l match {
    case Nil                         => Nil
    case Cons(head, tail) if f(head) => Cons(head, filterNumList(tail, f))
    case Cons(head, tail)            => filterNumList(tail, f)
  }
}

val l1 = Cons(12, Cons(25, Cons(37, Nil)))
def f1(j: Int): Boolean = j <= 25 && j >= 12
println(filterNumList(l1, f1))

您可以使用此代码here on Scastie

【讨论】:

  • 我不确定为什么这被否决了,这似乎很有帮助。如果有什么可以改进的,我很乐意这样做,但没有任何背景,这样做很难。
  • @stefanobaghino @DmytroMitin 我不确定我是如何偏离我的笔记的。我想我是出于绝望而想在纸上写一些东西。谢谢你们def map(l: List[Int], f: (Int) =&gt; Int): List[Int] = l match { case Nil =&gt; Nil case e :: rest =&gt; f(e) :: map(rest, f) }
  • @stefanobaghino How do I ask and answer homework questions? 1) “如果您认为这对学生没有帮助,最好不要提供完整的代码示例,使用您的最佳判断。” 2 ) “不要对真诚回答家庭作业问题的其他人投反对票,即使他们违反了这些准则” 删除反对票。
  • 感谢指出,我不知道。
  • @Garrett 我想稍后您将了解尾递归函数。遗憾的是,filter 的这种实现会产生 StackOverflow 错误(奇怪的是这个站点的名称)。如果您想深入研究该主题,只是一个快速提示,您需要一个累加器。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-13
  • 2018-10-16
  • 1970-01-01
  • 2012-02-07
  • 2015-04-27
  • 2010-11-16
相关资源
最近更新 更多