0

我在玩 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
    }
}

我可以使它仅适用于微不足道的情况。

这可以使用模式匹配来完成吗?我知道我可以使用列表中的方法使其工作,但这只是一个玩具程序。

4

3 回答 3

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)
  }
}

有关模式匹配中的反引号,请参见此答案

用法:

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
于 2013-03-28T03:42:11.387 回答
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
于 2013-03-28T03:44:34.543 回答
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)
于 2013-03-28T04:07:36.430 回答