2015-02-27 20 views
10

Tôi đã cố gắng sử dụng Map.map để chuyển đổi bản đồ thành Danh sách các bộ dữ liệu. Tuy nhiên điều này không thành công. Tôi đã thực hiện các thử nghiệm sau:Scala: ánh xạ Bản đồ vào danh sách các bộ dữ liệu

val m = Map(("a" -> 1), ("b" -> 2)) 
     //> m :  scala.collection.immutable.Map[String,Int] = Map(a -> 1, b -> 2) 
val r1 = m.map{ case (k,v) => v}    //> r1 : scala.collection.immutable.Iterable[Int] = List(1, 2) 
def toTuple[A,B](a:A,b:B) = (a,b)    //> toTuple: [A, B](a: A, b: B)(A, B) 
//val r2: List[Tuple2[_,_]] = m.map(e => (e._1,e._2)) 
val r3 = m.map(e => toTuple(e._1,e._2))   //> r3 : scala.collection.immutable.Map[String,Int] = Map(a -> 1, b -> 2) 
val r4 = m.toSeq        //> r4 : Seq[(String, Int)] = ArrayBuffer((a,1), (b,2)) 

Lưu ý cách tạo Danh sách cho các phần tử đơn (r1) nhưng Bản đồ được tạo cho bộ dữ liệu (r3). Thậm chí không ép buộc kiểu làm việc (r2). Chỉ có một cuộc gọi rõ ràng để Seq đã làm nó (r4) Vì vậy, câu hỏi của tôi là, tại sao/như thế nào Map.map "automagically" tạo ra một bản đồ mới và không phải là một danh sách ví dụ? Trong thực tế, loại trả lại được xác định như thế nào (Seq, Danh sách, v.v.)

+6

Điều gì sai với 'm.toList'? Cũng lưu ý rằng ánh xạ trên một bộ sưu tập trả về một bộ sưu tập cùng loại, vì vậy bạn không thể thực sự trả về ánh xạ danh sách trên một 'Bản đồ', trừ khi bạn gọi' .toList' trên nó. –

+0

@Ende - Không có gì sai. Xem bình luận dưới đây. – user2051561

Trả lời

14

A Map là một tập hợp các bộ dữ liệu đã có.

scala> "b" -> 2 
res0: (String, Int) = (b,2) // Implicitly converted to a Tuple 

Khi bạn đang ánh xạ một cặp (khóa, giá trị) chứa trong đó. Điều này không thể làm việc, bởi vì bạn đang loại bỏ các khóa, và chỉ giữ lại các giá trị. Vì vậy, những gì bạn có không còn là một Map, nhưng một bước hoặc hai lên hệ thống phân cấp bộ sưu tập, một Iterable:

val r1 = m.map{ case (k,v) => v} 

Buộc loại không thể làm việc, bởi vì một Map[A, B] không phải là một List[(A, B)]. Giá trị này tương đương với m.map(identity). Chú ý bạn thậm chí truy cập e với accessors tuple:

val r2: List[Tuple2[_,_]] = m.map(e => (e._1,e._2)) 

val r3 = m.map(e => toTuple(e._1,e._2)) 

Ở đây, Seq là hơn tổng quát hơn List:

val r4 = m.toSeq 

Giải pháp đơn giản như đã nêu bởi @EndeNeu là chỉ cần sử dụng toList. Khi bạn map một bộ sưu tập, nó sẽ trả lại loại bộ sưu tập gốc nếu có thể. Vì vậy, ánh xạ Map phải trả về một số Map khác, trừ khi cấu trúc bên dưới làm cho nó không còn là Map (như xóa hoàn toàn khóa) trong r1.

+0

Cảm ơn m-z. Câu hỏi của tôi thực sự là: trong trường hợp 'r1',' Map' biết nó sẽ chuyển đổi thành 'Danh sách' như thế nào? Nó có thể là cái gì khác? Tại sao không phải là một mảng? Tôi giả định của họ là một số chuyển đổi tiềm ẩn xảy ra ở đây. Do đó thử nghiệm của tôi bằng cách buộc các loại. Liên quan đến Tuples, có ý nghĩa. Đó là quy ước Bản đồ. – user2051561

+0

@ user2051561 Nó không chuyển đổi nó thành một 'Danh sách' trong' r1' - nó trả về 'Iterable' vì đó là đặc tính gần nhất tiếp theo trong hệ thống phân cấp phù hợp với loại bộ sưu tập bạn có. 'Bản đồ' mở rộng' Iterable'. –

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