2011-07-27 27 views
8

Thành ngữ Scala tốt nhất để khớp một giá trị với phần tử thứ n của danh sách là gì?Đối sánh với phần tử thứ n của danh sách trong Scala

Cách tiếp cận ngây thơ rõ ràng là không hoạt động:

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- câu hỏi này không phải là về làm thế nào để so sánh giá trị cho các yếu tố n-thứ của một danh sách - đó là đặc biệt về việc liệu nó có thể được thực hiện bằng cách sử dụng kết hợp.

+4

Nếu bạn cần lập chỉ mục vào chuỗi của mình, bạn nên sử dụng 'Vector' thay vì' Danh sách'. – missingfaktor

+1

Đúng, nhưng nếu hầu như tất cả các truy cập của tôi là đầu, và tôi chỉ rất hiếm khi cần tìm thêm một chút nữa, thì 'Danh sách' có thể vẫn hiệu quả hơn. –

Trả lời

17

Nầy, sức mạnh của nhổ ngay lập tức! (Lớp Regex trong stdlib hoạt động tương tự)

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

Đây là một ví dụ giải nén tuyệt vời, IMO, mặc dù có lẽ quá dài cho một lần. Nếu chỉ có một cách để làm điều đó mà không cần viết một vắt tùy chỉnh. –

+0

Lưu ý rằng 'in.size' là O (n); sử dụng 'Seq # lengthCompare' sẽ nhanh hơn trong nhiều trường hợp và không bao giờ chậm hơn. –

1

Không trực tiếp. Tuy nhiên, một trong những có thể làm:

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

hoặc

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

Ví dụ đầu tiên chỉ là so sánh với phần tử thứ n của danh sách bên trong một bảo vệ, đó là loại gian lận. Cái thứ hai giống như những gì tôi đang tìm kiếm. Điều xấu xí duy nhất về điều đó là tôi phải tham khảo phần tử thứ n trước trận đấu. –

3

bạn có thể phù hợp với danh sách:

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

scala> l(4) 
res13: Boolean = false 

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

Vâng, List không định nghĩa như một vắt, nhưng bạn có thể :

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 lưu ý rằng điều này sẽ luôn trả về kết quả trùng khớp đầu tiên. Kết hợp mẫu Scala không hoạt động như Prolog - nó không nạp 2 và xem điều đó có đúng không?

Các vấn đề liên quan