我正在玩scala模式匹配,试图创建一个findNext函数:
findNext(1,List(1,2,3)) == 2
findNext(2,List(1,2,3)) == 3
findNext(3,List(1,2,3)) == 1
def findNext(needle : Int, haystack : List[Int]): Int = {
haystack match {
case Nil => /* handle it */
case needle::Nil => needle
case front::needle::back => back.head
case needle::back::Nil => back.head
}
}
我可以让它只适用于琐碎的案例。
可以使用模式匹配来完成吗?我知道我可以使用列表中的方法使其工作,但这只是一个玩具程序。
答案 0 :(得分:3)
def findNext(needle : Int, haystack : List[Int]): Option[Int] = {
@annotation.tailrec def loop(needle : Int, haystack : List[Int], trueHead: Int): Option[Int] =
haystack match {
case Nil => None
case `needle` :: next :: _ => Some(next)
case `needle` :: Nil => Some(trueHead)
case _ :: tail => loop(needle, tail, trueHead)
}
haystack match {
case Nil | _ :: Nil => None
case _ => loop(needle, haystack, haystack.head)
}
}
有关模式匹配的后退标记,请参阅this answer。
用法:
scala> findNext(1,List(1,2,3))
res0: Option[Int] = Some(2)
scala> findNext(2,List(1,2,3))
res1: Option[Int] = Some(3)
scala> findNext(3,List(1,2,3))
res2: Option[Int] = Some(1)
scala> findNext(4,List(1,2,3))
res3: Option[Int] = None
scala> findNext(1,List(1,1))
res4: Option[Int] = Some(1)
scala> findNext(1,List(1))
res5: Option[Int] = None
scala> findNext(1,List())
res6: Option[Int] = None
答案 1 :(得分:2)
由于可能找不到针,最好在此处返回Option[Int]
。只使用模式匹配,您可以使用以下方法解决:
@tailrec def findNext(needle: Int, haystack: List[Int]): Option[Int] = {
haystack match {
case Nil => None
case front::next::back if front == needle => Some(next)
case head::tail => findNext(needle, tail)
}
}
甚至更简单:
@tailrec def findNext(needle: Int, haystack : List[Int]): Option[Int] = {
haystack match {
case Nil => None
case head::tail if head == needle => tail.headOption
case head::tail => findNext(needle, tail)
}
}
请注意,如果在haystack中找不到匹配项,则返回None,与上面的示例不同。然后可以将函数的结果与默认答案结合起来,如下所示:
val haystack = List(1,2,3,4)
findNext(4, haystack) getOrElse haystack.head
答案 2 :(得分:1)
如果在haystack
条件的帮助下最后一个元素是needle
,则该圈回到原始if
的头部。 findNextR
保存最后一个元素为needle
的情况的保存值。
def findNext(needle: Int, haystack: List[Int]): Option[Int] = {
@annotation.tailrec def findNextR(needle: Int, haystack: List[Int], savedHead: Int): Option[Int] = {
haystack match{
case Nil => None
case head :: tail => if (head == needle && tail.isEmpty) Some(savedHead)
else if (head == needle) Some(tail.head)
else findNextR(needle, tail, savedHead)
}
}
findNextR(needle, haystack, haystack.head)
}
scala> :load findNext.scala
Loading findNext.scala...
findNext: (needle: Int, haystack: List[Int])Option[Int]
scala> findNext(1, List(1,2,3))
res0: Option[Int] = Some(2)
scala> findNext(2, List(1,2,3))
res1: Option[Int] = Some(3)
scala> findNext(3, List(1,2,3))
res2: Option[Int] = Some(1)