匹配Scala中列表的第n个元素

时间:2011-07-27 06:10:24

标签: scala

将值与列表的第n个元素匹配的最佳Scala习惯用法是什么?

天真的方法显然不起作用:

scala> val list = List(5,6,7)
list: List[Int] = List(5, 6, 7)

scala> val x = 7
x: Int = 7

scala> x match { case list(2) => true; case _ => false }
<console>:10: error: value list is not a case class constructor, nor does it have an       unapply/unapplySeq method
   x match { case list(2) => true; case _ => false }

澄清 - 这个问题不是关于如何将值与列表的第n个元素进行比较 - 具体是关于是否可以使用匹配来完成。

4 个答案:

答案 0 :(得分:17)

看哪,实例提取器的力量! (stdlib中的Regex类的工作方式类似)

case class Nth[A](which: Int) {
  def unapply(in: List[A]): Option[A] = if (in.size >= which+1) Some(in(which)) else None
}

val second = Nth[Int](1)

List(2,4,6) match {
  case second(4) => println("yep!")
  case x => println("nope!")
}

答案 1 :(得分:3)

您可以匹配列表:

def l(X : Int) = list match { 
    case _ :: _ :: X :: _ => true 
    case _ => false
}

scala> l(4)
res13: Boolean = false

scala> l(7)
res14: Boolean = true

答案 2 :(得分:2)

好吧,List没有定义这样的提取器,但你可以:

scala> class IndexOf[T](seq: Seq[T]) {
     |   def unapply(x: T) = seq find (x ==) map (seq indexOf _)
     | }
defined class IndexOf

scala> val list = List(5,6,7)
list: List[Int] = List(5, 6, 7)

scala> val listndx = new IndexOf(list)
listndx: IndexOf[Int] = IndexOf@35cd1217

scala> val x = 7
x: Int = 7

scala> x match { case listndx(2) => true; case _ => false }
res2: Boolean = true

请注意,这将始终返回第一个匹配。 Scala模式匹配不像Prolog那样工作 - 它不提供2并查看是否可以某种方式为真。

答案 3 :(得分:1)

不直接。但是,其中一个可能会这样做:

x match { case _ if x == list(2) => true; case _ => false }

val listElem = list(2)
x match { case `listElem` => true; case _ => false }