2011-07-27 25 views
8

Bir değeri n-th öğesinin bir listeyle eşleştirmek için en iyi Scala deyimi nedir?Scala'da bir listenin n-th öğesine eşleşme

açıkçası naif yaklaşım çalışmaz:

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 } 

bu soruyu bir listenin n'inci öğesine bir değer karşılaştırmak konusunda değil clarify- için - o can konusunda spesifik olarak eşleme kullanılarak yapılmalıdır.

+4

Dizilerinize dizini eklemeniz gerekirse, 'List' yerine 'Vector' kullanarak daha iyi durumda olursunuz. – missingfaktor

+1

Doğru, ancak hemen hemen tüm erişimlerimin başına geldiysem ve çok nadiren biraz daha fazla bakmam gerekiyorsa, o zaman "Liste" genel olarak daha verimli olabilir. –

cevap

17

Bakın, örnek presi gücünü!

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

Bu mükemmel bir çıkarıcı örneğidir, IMO, muhtemelen bir defaya mahsus olmak üzere çok fazla verboldur. Özel bir çıkarıcı yazmadan sadece bunu yapmanın bir yolu olsaydı. –

+0

Not in.size 'nin O (n) olduğunu unutmayın; 'Seq # lengthCompare' kullanmak birçok durumda daha hızlı olur ve asla daha yavaş olmaz. –

1

Doğrudan değil. Ancak, bunlardan biri yapabilir:

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

veya

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

İlk örnek sadece bir muhafız içindeki bir listenin n-th elemanıyla karşılaştırılıyor, bu da aldatma anlamına geliyor. İkincisi, aradığım şey gibi. Bununla ilgili tek çirkin şey, maçtan önce n-inci öğesine başvurmam gerektiğidir. –

3

listeyi eşleşebilir (stdlib içinde Regex sınıf benzer şekilde çalışır):

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

scala> l(4) 
res13: Boolean = false 

scala> l(7) 
res14: Boolean = true 
2

Peki, List böyle bir aspiratör tanımlamıyor ama sen yapabilirsin :

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 Bu, her zaman ilk eşleşmesini döndürecektir. Scala desen eşleme Prolog gibi çalışmıyor - 2 beslemiyor ve bunun bir şekilde doğru olup olmadığına bakmıyor.