【问题标题】:Finding the nth element of a list in scala recursively with pattern matching使用模式匹配在scala中递归查找列表的第n个元素
【发布时间】:2014-08-20 10:32:27
【问题描述】:

我在 99 个 scala 问题 (http://aperiodic.net/phil/scala/s-99/p03.scala) 中遇到了一个问题,我试图弄清楚它是如何工作的。我对 Scala 还很陌生。我能够通过使用模式匹配和递归的类似解决方案完成这一挑战,但是我没有考虑匹配中的列表。我的代码如下:

def nth[A](k: Int, l: List[A]): A = k match {
  case 0 => l.head
  case _ => nth(k-1, l.drop(1))
}

这似乎完成了这项工作。但是,如果列表为 Nil,则不会检查错误。 99个scala问题提供的解决方案是:

def nthRecursive[A](n: Int, ls: List[A]): A = (n, ls) match {
  case (0, h :: _   ) => h
  case (n, _ :: tail) => nthRecursive(n - 1, tail)
  case (_, Nil      ) => throw new NoSuchElementException
}

我不明白的是

case(0, h:: _ )

case(n, _ :: tail)

作者在这里做什么?我了解 :: 将左侧的内容附加到右侧内容的开头,但我不确定到底发生了什么。谁能赐教?

谢谢!

【问题讨论】:

    标签: list scala recursion pattern-matching


    【解决方案1】:

    :: 运算符用于提取列表的头部和其余部分(尾部)。

    这里:

    case(0, h :: _ )
    

    只有头部是相关的,所以尾部没有得到参考。

    这里:

    case(n, _ :: tail)
    

    只有尾部是相关的,所以头部没有得到参考。

    你也可以使用:

    case(0, head :: tail)
    case(n, head :: tail)
    

    (即给两个部分一个参考)并得到完全相同的结果。

    【讨论】:

    • 所以基本上因为 _ 是通配符(匹配任何东西)但实际上并没有存储一些东西,所以匹配只会存储头部而忽略尾部?那很有意思。我想知道为什么 Scala 网站上的列表文档中没有涵盖该语法。
    【解决方案2】:

    基本上就是模式匹配表达式。这就是为什么 Scala 模式匹配如此强大的原因,所以我们可以删除一些像 Java 这样的重访问者模式(不在本主题中)。

    一个简单的例子:

    case class User(name: String, age: Int)
    
    def doStuff(user: User) = user match {
      case User(_, age) if age > 100 => println("Impossible!")
      case User(name, _) => println("hello " + name)
    }
    

    在这种情况下,_::tail 只是表示我想获取尾部的引用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-05-30
      • 1970-01-01
      • 2013-12-10
      • 1970-01-01
      • 2015-09-12
      • 2018-12-11
      • 2011-10-05
      相关资源
      最近更新 更多