C#:
In C# I have something like this:
IImmutableDictionary<string, string> map = new Dictionary<string, string>
{
{"K1", "V1"},
{"K2", "V2"},
{"K3", "V3"},
}.ToImmutableDictionary();
IEnumerable<string> keys = new[] {"K1,K3"};
map = map.RemoveRange(keys);
I assume that the method ImmutableDictionary<K,V>.RemoveRange Method (IEnumerable<K>)
was introduced since it is much more efficient than series of Remove(K)
calls. It creates the resulting immutable object only once instead of once for every element from keys
to remove.
F#:
What is the best way to achieve the same in F#. I came up with this recursive solution:
let rec removeAll (map:Map<string, string>, keys:list<string>) =
match keys with
| [] -> map
| _ -> removeAll(map.Remove(keys |> Seq.head), keys.Tail)
but I doubt it is as efficient as the RemoveRange
from above.
Questions:
RemoveAll
in F#? Assuming your set contains the strings you want to remove, you can use the keySet method and map. keySet(). removeAll(keySet); . keySet returns a Set view of the keys contained in this map.
To delete a key from a map, we can use Go's built-in delete function. It should be noted that when we delete a key from a map, its value will also be deleted as the key-value pair is like a single entity when it comes to maps in Go.
Map.filter
will be useful here and will presumably prevent creating many intermediate maps, though to use it efficiently for many keys you'll want to put the keys into a set first.
let removeAll keys map =
let keySet = set keys
map |> Map.filter (fun k _ -> k |> keySet.Contains |> not)
[ 1, 2
3, 4
5, 6
7, 8 ]
|> Map
|> removeAll [1; 5]
// map [(3, 4); (7, 8)]
This is small enough that it's potentially not worth breaking out into a function. For example in a case where you have an array of no more than 10 keys, then it may be less efficient to make a set out of them first.
Your current function is tail-recursive so it should be optimised in terms of not creating multiple stack frames, however you can write it a bit more simply by using pattern matching on the list:
let rec removeAll (map:Map<_,_>, keys:list<_>) =
match keys with
| [] -> map
| key :: rest -> removeAll(map.Remove(key), rest)
Also note that it can automatically be made generic by either removing type annotations or replacing parts of them with _
, telling the compiler to infer the type.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With