2011-07-27 129 views
8

將值與列表的第n個元素進行匹配的最佳Scala成語是什麼?匹配Scala中列表的第n個元素

顯然是幼稚的方法是行不通的:

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 } 

要clarify-這個問題不是關於如何將一個值進行比較,以列表的第n個元素 - 它專門是關於其能否使用匹配來完成。

+4

如果你需要索引你的序列,你最好使用'Vector'而不是'List'。 – missingfaktor

+1

的確如此,但是如果幾乎所有的訪問都是頭部的,而且我很少需要再進一步查看,那麼'List'總體上可能仍然更有效。 –

回答

17

看哪,例如提取的力量! (該Regex類的STDLIB工作方式類似)

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!") 
} 
+2

這是一個很好的提取器例子,IMO,雖然可能太冗長一次性。如果只是有一種方法可以不用編寫自定義提取器。 –

+0

請注意'in.size'是O(n);在很多情況下使用'Seq#lengthCompare'會更快,而且永遠不會變慢。 –

1

不直接。然而,這些人們可以做的:

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

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

第一個例子只是比較警衛內部的第n個元素,這是一種欺騙行爲。第二個更像我正在尋找的東西。關於那個唯一醜陋的事情是我必須在比賽前引用第n個元素。 –

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

好,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] = [email protected] 

scala> val x = 7 
x: Int = 7 

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

N請注意,這將始終返回匹配的第一個。 Scala模式匹配不能像Prolog一樣工作 - 它不會提供2並查看它是否可能是真的。

相關問題