2012-03-22 16 views
5

Tôi đang cố gắng tạo ra một biến thể Map với mặc định tạo ra một ListBuffer mới khi phần tử được yêu cầu chưa có trong bản đồ. Tuy nhiên, trong khi bản đồ mới được trả về làm mặc định nó không còn trong bản đồ. Có lẽ đây chỉ là cách nó hoạt động, tôi nghĩ, nhưng khi tôi thử nghiệm nó với một Int thay vì một ListBuffer nó đã làm chính xác như tôi muốn. Dưới đây là một số mã để giải thích những gì tôi có nghĩa là - tôi đang làm gì sai?Bản đồ với mặc định của một ListBuffer trống trong scala

Thứ nhất, ở đây nó đang làm việc với một Map[Int]:

scala> val a = collection.mutable.Map(1 -> 1).withDefault(i => 0) 
a: scala.collection.mutable.Map[Int,Int] = Map(1 -> 1) 

scala> a(1) += 1 // adding to an existing element works as expected 

scala> a 
res48: scala.collection.mutable.Map[Int,Int] = Map(1 -> 2) 

scala> a(2) += 1 // what about adding to a non-existing element? 

scala> a // the new element has been added to the map 
res50: scala.collection.mutable.Map[Int,Int] = Map(1 -> 2, 2 -> 1) 

Bây giờ với một Map[ListBuffer[Int]]:

scala> val b = collection.mutable.Map(1 -> collection.mutable.ListBuffer[Int]()).withDefault(i => collection.mutable.ListBuffer.empty[Int]) 
b: scala.collection.mutable.Map[Int,scala.collection.mutable.ListBuffer[Int]] = Map(1 -> ListBuffer()) 

scala> b(1) += 1 // appending to an existing element works as expected 
res51: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1) 

scala> b 
res52: scala.collection.mutable.Map[Int,scala.collection.mutable.ListBuffer[Int]] = Map(1 -> ListBuffer(1)) 

scala> b(2) += 1 // but appending to a non-existing element... 
res53: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1) 

scala> b // leaves the map unchanged 
res54: scala.collection.mutable.Map[Int,scala.collection.mutable.ListBuffer[Int]] = Map(1 -> ListBuffer(1)) 

Trả lời

3

Sự khác biệt là thế này:

Trong trường hợp đầu tiên a(2) là một Int . Vì Int không có phương thức +=, a(2) += 1 tương đương a(2) = a(2) + 1 và như vậy là a.update(2, a(2) + 1). update thực sự thay đổi bản đồ.

Nhưng ListBuffer[Int]không có một phương pháp +=, vì vậy cuộc gọi của bạn là a(2).+=(1), và bạn không đặt a(2) để bất cứ điều gì!

+0

Tuyệt vời, điều đó có ý nghĩa - vậy làm thế nào tôi có thể khắc phục? Tôi có cần phải làm điều đó qua ba dòng, nhận được phần tử, phụ thêm vào nó, sau đó thiết lập nó trở lại? Bởi vì tôi muốn tránh điều đó nếu có thể! – Russell

+0

Tôi cho rằng tôi có thể vẽ bản đồ (i) = map (i) + = 5 nhưng có vẻ khá crappy. – Russell

+1

Vâng, tôi nghĩ vậy (tất nhiên, bạn luôn có thể trích xuất điều này thành một phương thức trợ giúp tốt đẹp). –

1

Bạn có thể sử dụng getOrElseUpdate(key: A, op: => B) nơi bạn chỉ có thể tạo phiên bản mới của ListBuffer, khi khóa không có.

Ví dụ:

val m = collection.mutable.Map[Int, ListBuffer[Int]]() 
m.getOrElseUpdate(1, ListBuffer()) += 1 
+0

+1 bởi vì trong khi điều này có thể hơi khó chịu và kéo dài để viết, ý định * rõ ràng hơn rất nhiều. – Russell

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