问题:过滤映射中的元素,可以直接修改可变映射,也可以在不可变映射中应用过滤算法获得一个新的映射
解决方案:Use the retain
method to define the elements to retain when using a mutable map, and use filterKeys
or filter
to filter the elements in a mutable or immutable map, remembering to assign the result to a new variable.
You can filter the elements in a mutable Map using the retain method to specify which elements should be retained.
scala> var x = collection.mutable.Map(1 -> "a", 2 -> "b", 3 -> "c")
x: scala.collection.mutable.Map[Int,String] = Map(2 -> b, 1 -> a, 3 -> c)
scala> x.retain((k,v) => k > 1)
res0: scala.collection.mutable.Map[Int,String] = Map(2 -> b, 3 -> c)
scala> x
res1: scala.collection.mutable.Map[Int,String] = Map(2 -> b, 3 -> c)
As shown,
retain
modifies a mutable map in place. As implied by the anonymous function signature used in that example:
(k,v) => ...
Your algorithm can test both the key and value of each element to decide which elements to retain in the map.
In a related note, the transform
method doesn’t filter a map, but it lets you transform the elements in a mutable map:
scala> x.transform((k,v) => v.toUpperCase)
res0: scala.collection.mutable.Map[Int,String] = Map(2 -> B, 3 -> C)
scala> x
res1: scala.collection.mutable.Map[Int,String] = Map(2 -> B, 3 -> C)
Depending on your definition of “filter,” you can also remove elements from a map using methods like
remove
and
clear
.
Mutable and immutable maps
When working with a mutable or immutable map, you can use a predicate with thefilterKeys
methods to define which map elements to retain. When using this method,
remember to assign the filtered result to a new variable:
scala> val x = Map(1 -> "a", 2 -> "b", 3 -> "c") x: scala.collection.mutable.Map[Int,String] = Map(2 -> b, 1 -> a, 3 -> c) scala> val y = x.filterKeys(_ > 2) y: scala.collection.Map[Int,String] = Map(3 -> c)
The predicate you supply should return true
for the elements you want to keep in the new collection and false
for the elements you don’t want.
If your algorithm is longer, you can define a function (or method), and then use it in the filterKeys
call, rather than using an anonymous function. First define your method, such as this method, which returns true
when the value the method is given is 1:
scala> def only1(i: Int) = if (i == 1) true else false only1: (i: Int)Boolean
Then pass the method to the filterKeys
method:
scala> val x = Map(1 -> "a", 2 -> "b", 3 -> "c")
x: scala.collection.mutable.Map[Int,String] = Map(2 -> b, 1 -> a, 3 -> c)
scala> val y = x.filterKeys(only1)
y: scala.collection.Map[Int,String] = Map(1 -> a)
In an interesting use, you can also use a Set
with filterKeys
to define the elements to retain:
scala> var m = Map(1 -> "a", 2 -> "b", 3 -> "c")
m: scala.collection.immutable.Map[Int,String] = Map(1 -> a, 2 -> b, 3 -> c)
scala> val newMap = m.filterKeys(Set(2,3))
newMap: scala.collection.immutable.Map[Int,String] = Map(2 -> b, 3 -> c)
For instance, the Map
version of the filter
method lets you filter the map elements by either key, value, or both. The filter
method provides your predicate a Tuple2
, so you can access the key and value as shown in these examples:
scala> var m = Map(1 -> "a", 2 -> "b", 3 -> "c")
m: scala.collection.immutable.Map[Int,String] = Map(1 -> a, 2 -> b, 3 -> c)
// access the key
scala> m.filter((t) => t._1 > 1)
res0: scala.collection.immutable.Map[Int,String] = Map(2 -> b, 3 -> c)
// access the value
scala> m.filter((t) => t._2 == "c")
res1: scala.collection.immutable.Map[Int,String] = Map(3 -> c)
可以自定义一个方法fx(),将Tuple2传过去
var xxx = x.filter{case(k,v)=>fx(k,v)}
The take
method lets you “take” (keep) the first N elements from the map:
scala> m.take(2)
res2: scala.collection.immutable.Map[Int,String] = Map(1 -> a, 2 -> b)