2017-05-15 86 views
1

我正在尝试使用模式匹配在scala中查找列表的最后一个元素。我想下面的代码模式匹配找到列表的最后一个元素

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

最后一种情况,即案件_ =>无抛出错误类型不匹配(发现Nil.type要求A)

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

由于列表是泛型类型,所以我不能用N的缺省值替换,只能在运行时确定类型A的缺省值。

删除该行:case _ =>无显然正在工作,但有一个警告,它会在无参数的情况下失败。

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

回答

2

使用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}")) 
+0

有什么办法可以在这里指定类似于“Null”的东西(比如在Java中)泛型类型(这样我们可以避免使用Option)? – Shashank

+0

不推荐,因为这个想法是删除'null'的概念。最后一个元素可以是“某个值”或“空”。你有任何问题操纵返回的'Option'值? 'returnsValue match {}'是处理返回的最后一个值的方法 – prayagupd

+2

Shashank,在罕见的情况下,你可能会看到这样的情况,它在性能上有很大的差异,但它不会是惯用的Scala。请注意,在这种情况下,您必须将A限制为AnyRef,即'last [A <:AnyRef]'。 – AmigoNico

2

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

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

然后在你的代码,你可以使用单子一样的界面,结果工作。您可以使用map并在提供的功能中处理数据,也可以在选项中使用get方法,以防绝对确定列表不为空。

8

您可以模式匹配:+

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

不错。当然,也是尾递归的。恕我直言,这应该成为正确的答案。 – AmigoNico

相关问题