2014-04-23 20 views
9

Tôi có một m đồflatMap trên bản đồ cho lỗi: sai số tham số; dự kiến ​​= 1

val m = Map(1->2, 3->4, 5->6, 7->8, 4->4, 9->9, 10->12, 11->11) 

Bây giờ tôi muốn có một bản đồ có các phím đều bình đẳng với các giá trị. Vì vậy, tôi làm điều này

def eq(k: Int, v: Int) = if (k == v) Some(k->v) else None 
m.flatMap((k,v) => eq(k,v)) 

này mang lại cho tôi những lỗi

error: wrong number of parameters; expected = 1 
m.flatMap((k,v) => eq(k,v)) 

Whats sai với mã trên? flatMap mong đợi một hàm đối số và ở đây tôi đang chuyển một đối số là một cặp số nguyên.

Cũng làm việc này

m.flatMap { 
    case (k,v) => eq(k,v) 
} 

nhưng điều này không

m.flatMap { 
     (k,v) => eq(k,v) 
} 

Hình như tôi đang thiếu một cái gì đó. Cứu giúp?

+1

cảm ơn đã làm phiền tôi trong một thời gian dài –

Trả lời

6

(Nếu bạn muốn chỉ đơn giản là sửa chữa các lỗi mà bạn đang nhận được, thấy giải pháp thứ 2 (với flatMap);. Nếu bạn muốn có một giải pháp thường đẹp hơn, đọc từ đầu)

Những gì bạn cần thay là filter không flatMap:

def eq(k: Int, v: Int) = k == v 

val m = Map(1->2, 3->4, 5->6, 7->8, 4->4, 9->9, 10->12, 11->11) 

m.filter((eq _).tupled) 

... trong đó tất nhiên làm giảm chỉ sau đây, mà không cần eq:

m.filter { case (k, v) => k == v } 

kết quả:

Map(9 -> 9, 11 -> 11, 4 -> 4) 

HOẶC ... Nếu bạn muốn gắn bó với flatMap

Trước tiên, bạn phải biết rằng flatMap sẽ vượt qua các bộ chức năng của bạn không khóa và giá trị riêng biệt lập luận.

Thêm vào đó, bạn phải thay đổi Option trả về bởi eq một cái gì đó có thể được đưa trở lại để flatMap trên chuỗi như List hoặc Map (trên thực tế bất kỳ GenTraversableOnce để được chính xác):

def eq(k: Int, v: Int) = if (k == v) List(k -> v) else Nil 

m.flatMap { case (k,v) => eq(k,v) } // use pattern matching to unpack the tuple 

hoặc xấu xí nhưng tương đương:

m.flatMap { x => eq(x._1, x._2) } 

cách khác, bạn có thể chuyển đổi eq để lấy một bộ thay thế:

m.flatMap((eq _).tupled) 
3

Tôi nghĩ rằng những gì bạn muốn là một đối số duy nhất sẽ là một cặp vợ chồng, không phải là hai đối số.Một cái gì đó như thế này có thể hoạt động

m.flatMap(k => eq(k._1, k._2)) 

Đoạn mã hoạt động sử dụng kết hợp mẫu. Bạn đặt tên cho cả hai yếu tố của cặp đôi của bạn. Đó là một phần chức năng và có thể được sử dụng ở đây trong flatMap của bạn.

3

Bạn phải làm:

m.flatMap { case (k,v) => eq(k,v) } 

Lưu ý rằng ở đây tôi chuyển sang dấu ngoặc nhọn, mà chỉ ra một khối chức năng chứ không phải là thông số, và các chức năng đây là một tuyên bố như vậy. Điều này có nghĩa là khối chức năng tôi đang chuyển đến flatMap là một partialFunction chỉ được gọi cho các mục phù hợp với tuyên bố trường hợp.

1

Chức năng eq của bạn có hai tham số, đó là lý do bạn nhận được lỗi loại. Hãy thử:

def f(p: (Int, Int)) = if (p._1 == p._2) Some(p) else None 
m flatMap f 
7

Không có cú pháp như:

m.flatMap((k,v) => eq(k,v)) 

Vâng, trên thực tế có cú pháp như vậy, nhưng trên thực tế nó được sử dụng trong các chức năng chấp nhận hai đối số (như giảm):

List(1,2,3,4).reduce((acc, x) => acc + x) 

Các

m.flatMap { 
    case (k,v) => eq(k,v) 
} 

cú pháp làm việc bởi vì trong thực tế, nó là một cái gì đó như thế này:

val temp: PartialFunction[Tuple2[X,Y], Tuple2[Y,X]] = { 
    case (k,v) => eq(k,v) // using literal expression to construct function 
} 

m.flatMap(temp) // with braces ommited 

Họ Điều quan trọng ở đây là việc sử dụng case chữ (trên thực tế, có một cuộc thảo luận để cho phép rất cú pháp của bạn) which turns usual braces expression, như { ... } thành đầy đủ thổi vô danh chức năng một phần

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