2013-03-28 77 views
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 
    } 
} 

我可以使它只工作在平凡的情况。

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

回答

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 
+0

+1表示@tailrec,因为这是处理“下一个”的更直接简单的方法。 – wheaties 2013-03-28 03:52:24

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

注意,如果在草堆中找到匹配,不像你上面的例子返回值为None。该函数的结果,然后可以用默认的回答结合起来,就像这样:

val haystack = List(1,2,3,4) 
findNext(4, haystack) getOrElse haystack.head 
+0

对于'FindNext中(3,列表(1,2,3))== 1'此返回'选项[INT] = None'其中示例显示它返回'haystack'的头部。 – Brian 2013-03-28 03:52:33

+2

添加了关于此的注释。我不确定作者是否打算这样做。 – 2013-03-28 03:57:19

+0

@alexwriteshere是的,“FindNext中”动作应该是圆形的。这虽然是巨大的帮助。 – Tom 2013-03-28 04:03:50

1

这个圈子回到原来haystack的头,如果最后一个元素是needleif条件语句的帮助。该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)