2012-11-14 48 views
26

Tôi có một cấu trúc lớp như thế nàyLọc một danh sách Scala theo loại

và tôi có một bộ sưu tập của các trường hợp khác nhau, ví dụ:

val xs = List(new D, new B, new E, new E, new C, new B) 

Câu hỏi của tôi là, liệu có một cách thanh lịch để lọc ra một số lớp con khỏi Danh sách?

Giả sử tôi muốn tất cả các trường hợp ngoại trừ B và C. Tôi có thể làm điều đó với một loạt các isInstanceOf, hoặc bằng cách sử dụng thu thập như thế này:

val ys = (xs collect { 
    case b: B => None 
    case c: C => None 
    case notBorC => notBorC 
}).filter(_ != None).asInstanceOf[List[A]] 

này hoạt động nhưng nó cảm thấy lúng túng, chủ yếu là vì các bộ lọc và đúc. Có cách nào thanh lịch hơn không? Ít mã được ưu tiên và tôi muốn có giải pháp không cần phải cập nhật nếu tôi thêm các lớp con khác của A.

Trả lời

34

flatMap rằng shit! (as they say):

scala> val ys = xs flatMap { 
    | case _: B | _: C => None 
    | case other => Some(other) 
    | } 
ys: List[A] = List([email protected], [email protected], [email protected]) 

Trong trường hợp của bạn, bạn đã nhận được một List[ScalaObject]ScalaObject là đơn giản nhất trên ràng buộc của None, D, và E.

+0

Vâng, đây là giải pháp tốt hơn nhiều so với lần thử đầu tiên của tôi. – hezamu

3

Xây dựng các vấn đề như câu hỏi có vẻ là cách khá tốt để giải quyết chúng :) câu hỏi của tôi thực sự cung cấp câu trả lời - chỉ cần lọc theo kiểu phụ:

val ys = xs filterNot(List(classOf[B], classOf[C]) contains _.getClass) 
+0

Nếu bạn có ý định rằng '' ys'' là danh sách trống nếu danh sách loại trừ của bạn chứa '' classOf [A] '', thì bạn sẽ cần một cái gì đó khác đi. Ví dụ: '' xs.filterNot (x => List (classOf [A]). Tồn tại (y => y.isInstance (x))) ''. Travis 'giải pháp trưng bày tài sản này là tốt. –

+0

@mhs: Đúng vậy, mặc dù trong trường hợp của tôi A là trừu tượng để có nó trong danh sách loại trừ không liên quan. Dù sao, tôi đồng ý rằng giải pháp flatMap của Travis cũng vượt trội so với giải pháp này. – hezamu

+0

Không, tôi không đồng ý rằng giải pháp travis nhất thiết phải vượt trội so với giải pháp của bạn. Của bạn có thể được abstracted trong tập hợp các lớp học bạn muốn lọc ra, giải pháp Travis 'không thể được tóm tắt theo hướng đó. Nhưng bạn sử dụng một tập hợp thay vì một danh sách trong đối số để lọcNot. – jmg

45

collect có thể được sử dụng để lọc các giá trị mà hàm được định nghĩa:

Nhận tất cả các giá trị của loại A:

xs.collect { case a: A => a } 

Nhận tất cả các giá trị ngoại trừ B và C:

xs diff xs.collect { case [email protected](_: B | _: C) => x } 
Các vấn đề liên quan