简体   繁体   English

在F#中从地图中删除所有

[英]RemoveAll from map in F#

C#: C#:

In C# I have something like this: 在C#我有这样的事情:

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. 我假设引入了ImmutableDictionary<K,V>.RemoveRange Method (IEnumerable<K>) ,因为它比一系列Remove(K)调用更有效。 It creates the resulting immutable object only once instead of once for every element from keys to remove. 它仅为要删除的keys每个元素创建一次生成的不可变对象,而不是一次。

F#: F#:

What is the best way to achieve the same in F# . 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. 但我怀疑它和上面的RemoveRange一样有效。

Questions: 问题:

  1. What is the most efficient equivalent of RemoveAll in F#? F#中RemoveAll最有效的等价物是什么?
  2. Do you think F# recursion optimization is going to compile to something equally efficient? 你认为F#递归优化是否会编译成同样有效的东西?

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. Map.filter在这里很有用,可能会阻止创建许多中间贴图,但是要有效地使用它,你需要先将键放入一组中。

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. 例如,如果您的数组不超过10个键,那么首先设置它们的效率可能会低一些。

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. 另请注意,它可以通过删除类型注释或用_替换它们的一部分来自动变为通用,告诉编译器推断类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM