我很难加入Map.remove一系列密钥.
例如,如果我有
let z : Map<int, Set<int>> = Map.ofList [(1, set []); (3, set [3; 4]); (4, set [])]
Run Code Online (Sandbox Code Playgroud)
我想programmaticaly找到每个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
Run Code Online (Sandbox Code Playgroud)
这给了我
[1; 4]
Run Code Online (Sandbox Code Playgroud)
这正是我所期待的.但是现在,如果我想key, value从地图中删除这些对,我能想到的唯一方法就是将原始内容Map转换为如下列表:
z
|> Map.toList
|> List.filter (fun (k, s) -> not (emptySets
|> List.contains k))
Run Code Online (Sandbox Code Playgroud)
这让我回到了我期待的地图.
当我这样做
emptySets
|> List.map (fun i -> Map.remove i z)
Run Code Online (Sandbox Code Playgroud)
我找回了地图列表.
有没有办法可以用来Map.remove从给定地图中删除键列表而不返回地图列表?
每次Map.remove通话都会给你一个新的map- 与"旧的"相同,但没有那个项目.旧地图仍然完好无损,您仍然可以使用它,但如果您继续使用它,您仍会看到已删除的项目,因为它仍然在旧地图中.如果要在没有删除项目的情况下执行下一个操作,则必须在"新"映射上执行这些操作 - 从中返回的操作Map.remove,不包含项目的操作.
let m0 = // create the map
let m1 = Map.remove 1 m0
let m2 = Map.remove 4 m1
Run Code Online (Sandbox Code Playgroud)
注意每个操作如何使用前一个操作的结果.当你有一个完整的这类操作列表时,每个下一个必须使用前一个的结果,从而在某种意义上"累积"结果 - 这就是所谓的fold.该fold函数有三个方面:初始累计值,取前一个值并生成下一个值的函数,以及输入列表:
let mapFinal= List.fold (fun mapPrev key -> Map.remove key mapPrev) mapInitial keys
Run Code Online (Sandbox Code Playgroud)
也许我错过了一些观点,但是简单地使用Map.filter以保持值设置不为空的项目而不是删除值集合为空的所有项目是不是更容易?
此外,它使用起来要简单得多,Set.isEmpty而不是转换为列表获取它的长度并检查它是否为0.
Map.filter (fun _ -> not << Set.isEmpty) z
// val it : Map<int,Set<int>> = map [(3, set [3; 4])]
Run Code Online (Sandbox Code Playgroud)