2013-01-17 42 views
5

Do sau:Trích xuất một giá trị từ một tùy chọn bên trong một tùy chọn trong Scala

val x = Some(Some(1)) 

Điều gì sẽ là cách sạch để có được 1 (hoặc -1 nếu một trong những không tồn tại)?

Tôi đang tạo một đối tượng đối tượng từ một bộ dữ liệu được trả về từ truy vấn cơ sở dữ liệu. Một trong những giá trị trong tuple trông như thế này, vì vậy tôi muốn một đoạn ngắn 'một lớp lót' ngắn để có được giá trị hoặc đặt tham số là -1.

Trả lời

15

x.flatten là những gì bạn đang tìm kiếm. Ở đây nó sẽ cung cấp cho bạn Some(1). Nếu bạn thực sự muốn có được -1 cho trường hợp "một sự không tồn tại", chỉ cần làm x.flatten.getOrElse(-1):

scala> Some(Some(1)).flatten.getOrElse(-1) 
res1: Int = 1 
scala> Some(None).flatten.getOrElse(-1) 
res2: Int = -1 
scala> None.flatten.getOrElse(-1) 
res3: Int = -1 
+1

Flatten !!! Tôi đã đọc nó, tôi đã nhìn thấy nó, tôi đã sử dụng nó ... bây giờ chỉ cần nhớ nó ;-) – Jack

1

Đây là những gì tôi đã đưa ra:

scala> val x = Some(Some(1)) 
x: Some[Some[Int]] = Some(Some(1)) 

scala> val y = x.map(_.getOrElse(-1)).get 
y: Int = 1 

scala> val x = Some(None) 
x: Some[None.type] = Some(None) 

scala> val y = x.map(_.getOrElse(-1)).get 
y: Int = -1 

Tính năng này chỉ hoạt động khi cấp độ đầu tiên của bạn Một số không phải là Không có

+0

+1 Đó là chính xác một trong những con đường tôi đã ;-) Điều đó, và 'phù hợp', nhưng Tôi biết có một cách để có được nó trong một đi đơn giản, nhưng không thể nhớ như thế nào. Flatten thực hiện phép thuật mà tôi đang tìm kiếm. – Jack

+0

Có giải pháp khác rõ ràng là đẹp hơn. Tôi cũng luôn quên làm phẳng. ;-) –

1

Mặc dù không phải là "một lớp phủ" bạn có thể tạo một hàm để trích xuất giá trị. Nếu bạn làm cho nó chung chung và vượt qua trong giá trị mặc định nó có thể khá tiện dụng.

scala> def fetchFromOptions[A](default: A)(x: Option[Option[A]]) = x match { 
    | case Some(Some(a)) => a 
    | case _ => default 
    | } 
fetchFromOptions: [A](default: A)(x: Option[Option[A]])A 

scala> fetchFromOptions(-1)(Some(Some(1))) 
res0: Int = 1 

scala> fetchFromOptions(-1)(Some(None)) 
res1: Int = -1 
1

Nếu bạn thực sự biết rằng nó Some(Some(1)), sau đó bạn có thể sử dụng các ký hiệu mô hình trận đấu không thể chối cãi:

scala> val ssi1 = Some(Some(1)) 
ssi1: Some[Some[Int]] = Some(Some(1)) 

scala> val Some(Some(i1)) = ssi1 
i1: Int = 1 

Nếu có thể có bất kỳ khả năng None trong hỗn hợp, sau đó bạn phải sử dụng các hình thức thận trọng và dài dòng hơn được đề xuất bởi những người khác.

Đối với những người tìm thấy điều này một ký hiệu kỳ lạ, nghĩ về nó như những gì bạn muốn viết trong một case trong một cấu trúc match hoặc PartialFunction đen để phù hợp với một scrutinee đó là Some(Some(1)).

2

cho-comprehensions thường là một cách rất có thể đọc được sử dụng các loại cấu trúc lồng nhau:

val x = Some(Some(1)) 
    val result = for { 
    firstLevel <- x 
    secondLevel <- firstLevel 
    } yield { 
    // We've got an int, now transform it! 
    (secondLevel * 100).toString 
    } 

Kết quả là một lựa chọn [Chuỗi], và việc chuyển đổi chỉ xảy ra khi bạn có hai Một số (s) .

Bạn cũng có thể sử dụng mô hình phù hợp:

val result2 = for { 
    Some(v) <- x 
    } yield { 
    // We've got a int, now transform it! 
    (v * 100).toString 
    } 
Các vấn đề liên quan