2012-02-15 22 views
6

Đối với bản đồ trong Scala, nếu ms - (k, 1, m) trả về bản đồ có chứa tất cả ánh xạ của ms ngoại trừ cho bất kỳ ánh xạ nào với các phím đã cho, x, 1 và m.Bản đồ chỉ với các phím nhất định

Sau đó, câu lệnh nào sẽ trả về bản đồ của tất cả ánh xạ của các ms với chỉ các khóa đã cho, x, 1 và m. tức là tôi đang tìm tập hợp con của các ms chỉ có k, 1 và m là các khóa.

này hoạt động, nhưng nó là khủng khiếp:

scala> val originalMap = Map("age" -> "20", "name" -> "jack", "hobby" -> "jumping") 
ms: scala.collection.immutable.Map[java.lang.String,java.lang.String] = Map(age -> 20, name -> jack, hobby -> jumping) 

scala> val interestingKeys = List("name", "hobby") 
interesting: List[java.lang.String] = List(name, hobby) 

scala> val notInterestingMap = originalMap -- interestingKeys 
notInterestingMap: scala.collection.immutable.Map[java.lang.String,java.lang.String] = Map(age -> 20) 

scala> val interestingMap = originalMap -- notInterestingMap.keySet 
interestingMap: scala.collection.immutable.Map[java.lang.String,java.lang.String] = Map(name -> jack, hobby -> jumping) 

Trả lời

7

filterKeys bộ lọc dựa trên một vị tùy ý, nó phải xem xét tất cả các quan trọng trong bản đồ. Điều này có thể tốt hay không, tùy thuộc vào bản đồ lớn như thế nào, v.v., nhưng chắc chắn không cần thiết cho hoạt động bạn mô tả. Tôi muốn sử dụng một cái gì đó như sau:

interestingKeys.flatMap(k => originalMap.get(k).map((k, _))).toMap 

Đây sẽ là O(n) hoặc O(n log m) tùy thuộc vào thực hiện bản đồ của bạn (nơi n là kích thước của interestingKeysm được kích thước của bản đồ), thay vì hoặc O(mn) .

Nếu bạn thực sự muốn điều hành ~ của bạn, bạn có thể sử dụng pimp-my-library pattern:

class RichMap[A, B](m: Map[A, B]) { 
    def ~(ks: A*) = ks.flatMap(k => m.get(k).map((k, _))).toMap 
} 

implicit def enrichMap[A, B](m: Map[A, B]) = new RichMap(m) 

Bây giờ originalMap ~ ("name", "hobby") lợi nhuận Map(name -> jack, hobby -> jumping), như bạn mong muốn.

+0

Đối với những người sử dụng AKKA kiên trì, nó đáng nói rằng đầu ra 'filterKeys' là _not_ serializable, tôi phải đối mặt với điều đó và phải mất một lúc cho đến khi tôi nhận ra. Xem https://issues.scala-lang.org/browse/SI-6654 –

7

filterKeys có thể giúp:

scala> originalMap.filterKeys(interestingKeys.contains) 
res0: scala.collection.immutable.Map[java.lang.String,java.lang.String] = Map(name -> jack, hobby -> jumping) 
+2

có thể cải thiện với thú vịKeys.toSet' thay vì 'interestingKeys contains', vì việc kiểm tra tư cách thành viên thành tập hợp có thể sẽ hiệu quả hơn. Tuy nhiên, không có danh sách hai yếu tố. –

+1

và không nếu bạn vượt qua một danh sách các yếu tố phân biệt. Nó rõ ràng phụ thuộc vào ngữ cảnh. – Nicolas

+2

Tại sao các yếu tố khác biệt lại thay đổi điều đó? Kiểm tra tư cách thành viên sẽ vẫn là O (n) thay vì O (1) hoặc O (log n) để thực hiện thiết lập điển hình. –

1

Tôi nghĩ rằng mã gốc không phải là xấu, và nó có thể dễ dàng chuyển đổi thành một lớp lót hoạt động trên bộ chủ chốt:

val interestingMap = originalMap -- (originalMap.keySet -- interestingKeys) 

Tôi tìm thấy điều này khá dễ đọc.

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