2008-09-10 35 views
16

Gần đây tôi đã làm việc cho dự án của người mới bắt đầu ở Scala, và có một câu hỏi mới bắt đầu về Danh sách của Scala.Trả về một phần tử từ một Danh sách trong Scala

Giả sử tôi có danh sách các bộ dữ liệu (ví dụ: List[Tuple2[String, String]]). Có phương pháp tiện lợi nào để trả về lần xuất hiện đầu tiên của một bộ dữ liệu được chỉ định từ Danh sách hay là cần thiết để lặp qua danh sách bằng tay?

Trả lời

6

Bạn có thể thử sử dụng find. (Đã cập nhật vị trí của scala-doc về tìm kiếm)

2

Nếu bạn đang học scala, tôi sẽ xem xét tốt đặc tính Seq. Nó cung cấp cơ sở cho phần lớn chức năng của scala.

+0

Liên kết bị hỏng. – ctford

+0

Liên kết hoạt động. – akauppi

13
 
scala> val list = List(("A", "B", 1), ("C", "D", 1), ("E", "F", 1), ("C", "D", 2), ("G", "H", 1)) 
list: List[(java.lang.String, java.lang.String, Int)] = List((A,B,1), (C,D,1), (E,F,1), (C,D,2), (G,H,1)) 

scala> list find {e => e._1 == "C" && e._2 == "D"} 
res0: Option[(java.lang.String, java.lang.String, Int)] = Some((C,D,1)) 
+2

Có thể trả lại không một số ((C, D, 1)) nhưng (C, D, 1)? Tôi có nghĩa là cùng một cách nếu tôi sẽ sử dụng danh sách (1). – grass

+2

@grass Giá trị trả về sẽ là gì nếu không tìm thấy 'ba (C, D, 1)' trong danh sách? –

+1

Không có hoặc ngoại lệ hoặc bộ trống. Sẽ là tuyệt vời nếu có một cách để tùy chỉnh giá trị trả lại nếu không tìm thấy ba (ngoại trừ viết phương thức find() của riêng tôi). – grass

3

Như đã đề cập trong nhận xét trước, find có lẽ là cách dễ nhất để thực hiện việc này. Thực tế có ba phương thức "tìm kiếm tuyến tính" khác nhau trong các bộ sưu tập của Scala, mỗi bộ trả về một giá trị hơi khác một chút. Mà một trong những bạn sử dụng phụ thuộc vào những gì bạn cần dữ liệu cho. Ví dụ, bạn cần một chỉ mục, hay bạn chỉ cần một boolean true/false?

+0

Bạn có thể cung cấp thêm thông tin về các phương pháp "tìm kiếm tuyến tính" này không? Tôi đang tìm kiếm để có được chỉ số của một tuple (chỉ có một phần của tuple) – krookedking

+0

thực sự tôi đã tìm thấy những gì tôi đã tìm kiếm: '.zipWithIndex.collect {case (" partOfTuple ", _, i) => i } ' – krookedking

1

Bạn cũng có thể làm được điều này, mà không yêu cầu biết tên trường trong lớp Tuple2 - nó sử dụng mô hình kết hợp thay vì:

list find { case (x,y,_) => x == "C" && y == "D" } 

"tìm" là tốt khi bạn biết bạn chỉ cần một ; nếu bạn muốn tìm tất cả các yếu tố phù hợp, bạn có thể sử dụng "bộ lọc" hoặc đường tương đương để hiểu:

for ((x,y,z) <- list if x == "C" && y == "D") yield (x,y,z) 
+1

Ví dụ thứ hai của bạn dường như hoạt động nhiều hơn như' filter', tức là nó sẽ trả về * tất cả * các phần tử khớp với thuộc tính, chứ không phải là phần tử đầu tiên duy nhất mà tác giả câu hỏi muốn nó. –

1

Đây là mã có thể giúp bạn.

Tôi đã có một trường hợp tương tự, có một tập hợp các mục cơ sở lớp (ở đây, A) trong đó tôi muốn tìm một nút của lớp dẫn xuất nhất định, nếu có (ở đây, B).

class A 

case class B(val name: String) extends A 

object TestX extends App { 
    val states: List[A] = List(B("aa"), new A, B("ccc")) 

    def findByName(name: String): Option[B] = { 
    states.find{ 
     case x: B if x.name == name => return Some(x) 
     case _ => false 
    } 
    None 
    } 

    println(findByName("ccc")) // "Some(B(ccc))" 
} 

Phần quan trọng đây (đối với ứng dụng của tôi) là findByName không trả lại Option[A] nhưng Option[B].

Bạn có thể dễ dàng sửa đổi hành vi để trả lại B thay thế và ném một ngoại lệ nếu không tìm thấy. Hi vọng điêu nay co ich.

1

Cân nhắc collectFirst mang lại Some[(String,String)] cho tuple phù hợp đầu tiên hoặc None khác, ví dụ như sau,

xs collectFirst { case [email protected](a,_) if a == "existing" => t } 
Some((existing,str)) 

scala> xs collectFirst { case [email protected](a,_) if a == "nonExisting" => t } 
None 

Sử dụng @ chúng ta ràng buộc giá trị của tuple để t để một tuple toàn phù hợp có thể được thu thập .

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