【问题标题】:Pattern matching to find last element of list模式匹配以查找列表的最后一个元素
【发布时间】:2017-05-15 05:20:09
【问题描述】:

我正在尝试使用模式匹配在 Scala 中查找列表的最后一个元素。我尝试了以下代码

def last[A](list: List[A]):A = list match {
 case head :: Nil => head
 case head :: tail => last(tail)
 case _ => Nil
 }

最后一种情况,即case _ => Nil,由于类型不匹配而引发错误(发现 Nil.type 需要 A)

我知道这个问题可以用其他方法解决,但是只使用模式匹配有没有办法解决这个问题?

由于列表是泛型类型,所以我无法将 Nil 替换为 A 类型的默认值,该值只能在运行时确定。

删除这一行:case _ => Nil 显然可以正常工作,但警告说如果出现 Nil 参数,它将失败。

那么,在这种情况下如何处理 Nil 参数?

【问题讨论】:

    标签: scala pattern-matching


    【解决方案1】:

    您可以使用:+进行模式匹配。

    def last[A](list: List[A]) = list match {
      case init :+ last => Some(last)
      case _ => None
    }
    

    【讨论】:

    • 不错。当然,还有尾递归。恕我直言,这应该成为正确的答案。
    • 是否有类似的提取器仅用于最后一个元素?也就是说,_ :+ last 不匹配像 List(1) 这样的单例列表。
    • @ComFreek val _ :+ last = List(1) 虽然对我有用。
    • 谁能解释一下:+ last是如何变成A类型的值的?阅读这个例子我的期望是List[A]
    • @Sergii 这只是一个custom extractor。没有什么神奇的事情发生。
    【解决方案2】:

    由于您不确定您的列表是否包含任何对象,您应该以一般方式处理这种情况。我建议在您的 last 方法中返回选项类型,如下所示:

    def last[A](list: List[A]): Option[A] = list match {
        case head :: Nil => Some(head)
        case head :: tail => last(tail)
        case _ => None
    }
    

    然后在您的代码中,您可以使用类似 monad 的界面来处理结果。您可以使用map 并在提供的函数中处理数据,或者在选项上使用get 方法,以防您绝对确定列表不为空。

    【讨论】:

      【解决方案3】:

      使用Option[T]返回结果,如果有元素返回Some(lastElement)否则Option.empty

      例子,

        def last[A](list: List[A]): Option[A] = list match {
          case head :: Nil => Option(head)
          case head :: tail => last(tail)
          case _ => Option.empty
        }
      
        it("returns last element") {
      
          assert(last(List("apple")) == Some("apple"))
          assert(last(List("apple", "mango")) == Some("mango"))
          assert(last(List()) == Option.empty)
          assert(last(List()) == None)
      
        }
      

      如何访问Option[T]

      last(List("In absentia", "deadwind")) match {
        case Some(lastValue) => println(s"Yayy there was lastValue = ${lastValue}") //prints Yayy there was lastValue = deadwind
        case None => println("Oops list was empty")
      }
      
      last(List()) match {
        case Some(lastValue) => println(s"Yayy there was lastValue = ${lastValue}")
        case None => println("Oops list was empty") //prints Oops list was empty
      }
      
      // or using map
      last(List("In absentia", "deadwind")).map(lastValue => print(s"lastValue is ${lastValue}"))
      

      【讨论】:

      • 有没有办法在这里为泛型类型指定类似于“Null”的东西(就像在Java中一样)(这样我们就可以避免使用Option)?
      • 不推荐,因为这个想法是删除null的概念。最后一个元素可以是some valueempty。您在处理返回的Option 值时遇到任何问题吗? returnedValue match {}是处理返回最后一个值的方式
      • Shashank,你可能会在极少数情况下看到这样的东西,它会对性能产生巨大影响,但它不是惯用的 Scala。请注意,在这种情况下,您必须将 A 限制为 AnyRef,即 last[A <: AnyRef]
      • @AmigoNico:是的,如果我们这样想是有道理的......谢谢
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-05-25
      • 2011-10-05
      • 1970-01-01
      • 2013-09-03
      • 1970-01-01
      • 1970-01-01
      • 2020-02-23
      相关资源
      最近更新 更多