使用Map.remove和键列表

时间:2016-12-01 15:11:59

标签: f#

我很难将Map.remove与一系列密钥合并。

例如,如果我有

let z : Map<int, Set<int>> = Map.ofList [(1, set []); (3, set [3; 4]); (4, set [])]

我希望以编程方式查找key, value为空的每个value,我可以这样做:

let emptySets = 
    z
    |> Map.toList
    |> List.map (fun (k, s) -> (k, s |> Set.toList |> List.length))
    |> List.filter (fun (k, i) -> i = 0)
    |> List.map fst

这给了我

[1; 4]

这正是我所期待的。但是现在,如果我想从地图中删除这些key, value对,我能想到的唯一方法是将原始Map转换为这样的列表:

z
|> Map.toList
|> List.filter (fun (k, s) -> not (emptySets 
                                   |> List.contains k))

这让我回到了我期待的地图。

当我这样做时

emptySets
|> List.map (fun i -> Map.remove i z)

我找回了地图列表。

有没有办法可以使用Map.remove从给定地图中删除键列表而不获取地图列表?

3 个答案:

答案 0 :(得分:8)

每次Map.remove来电都会返回一个新的map - 与&#34; old&#34;相同一个,但没有那个项目。旧地图仍然完好无损,您仍然可以使用它,但如果继续使用它,您仍会看到已删除的项目,因为它仍然在旧地图中。如果您想在没有删除项目的情况下执行下一步操作,则必须在&#34; new&#34;上执行这些操作。 map - 从Map.remove返回的那个,不包含该项目的那个。

let m0 = // create the map
let m1 = Map.remove 1 m0
let m2 = Map.remove 4 m1

注意每个操作如何使用前一个操作的结果。当你有一个这样的操作的完整列表时,每个下一个必须使用前一个的结果,因此&#34;累积&#34;结果在某种意义上, - 称为foldfold函数有三个方面:初始累计值,取前一个值并生成下一个值的函数,以及输入列表:

let mapFinal= List.fold (fun mapPrev key -> Map.remove key mapPrev) mapInitial keys

答案 1 :(得分:5)

也许我错过了一些观点,但是简单地使用Map.filter来保存值设置不为空的项目而不是删除值集合为空的所有项目是不是更容易?

使用Set.isEmpty而不是转换为列表获取它的长度并检查它是否为0也更简单。

Map.filter (fun _ -> not << Set.isEmpty) z
// val it : Map<int,Set<int>> = map [(3, set [3; 4])]

答案 2 :(得分:4)

您可以使用折叠:

let z : Map<int, Set<int>> = Map.ofList [(1, set []); (3, set [3; 4]); (4, set [])]
let keysToRemove = [1;2]
List.fold (fun x i -> Map.remove i x) z keysToRemove

// val it : Map<int,Set<int>> = map [(3, set [3; 4]); (4, set [])]