List 使用模式匹配查找列表中的下一个元素

List 使用模式匹配查找列表中的下一个元素,list,scala,pattern-matching,List,Scala,Pattern Matching,我正在玩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 nee

我正在玩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
    }
}
我能让它只对一件小事起作用

这可以通过模式匹配来实现吗?我知道我可以使用列表中的方法使它工作,但这只是一个玩具程序

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
有关模式匹配中的回标记,请参见

用法:

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

由于可能找不到指针,因此最好在此处返回
选项[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

由于可能找不到指针,因此最好在此处返回
选项[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

如果最后一个元素是
,则在
if
条件的帮助下,该循环回到原始
haystack
的头部。
findNextR
保存最后一个元素为
指针时的保存值

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)

如果最后一个元素是
,则在
if
条件的帮助下,该循环回到原始
haystack
的头部。
findNextR
保存最后一个元素为
指针时的保存值

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)

+1表示建议@tailrec,因为这是处理“下一步”更直接、更简单的方法。+1表示建议@tailrec,因为这是处理“下一步”更直接、更简单的方法。
findNext(3,List(1,2,3))==1
这将返回
选项[Int]=无
,示例显示它返回了
干草堆的头部
。添加了关于此的注释。我不确定作者是否有意这样做。@alexwriteshere是的,“findNext”操作应该是循环的。不过,这帮了大忙。
findNext(4,List(1))getOrElse haystack.head==1
对于
findNext(3,List(1,2,3))==1
这将返回
选项[Int]=None
,示例显示它返回
干草堆的头部。添加了一个关于此的注释。我不确定作者是否有意这样做。@alexwriteshere是的,“findNext”操作应该是循环的。这对我们帮助很大。
findNext(4,List(1))getOrElse haystack.head==1