模式匹配现有变量

时间:2014-04-03 14:21:47

标签: recursion map f# nested

我有嵌套地图的结构:

[<RequireQualifiedAccess>]
type NestedMap =
    | Object of Map<string,NestedMap>
    | Value of int    

我需要修剪结构。 代码的目的是保持映射的嵌套结构和找到键值对的映射的完整性,修剪未找到键值对的分支。

以下是测试NestedMap

let l2'  = NestedMap.Object ( List.zip ["C"; "S"; "D"] [NestedMap.Value(10); NestedMap.Value(20); NestedMap.Value(30)] |> Map.ofList)
let l3   = NestedMap.Object ( List.zip ["E"; "S"; "F"] [NestedMap.Value(100); NestedMap.Value(200); NestedMap.Value(300)] |> Map.ofList)    
let l2'' = NestedMap.Object ( List.zip ["G"; "H"; "I"; "S"] [NestedMap.Value(30); l3; NestedMap.Value(40); NestedMap.Value(50)] |> Map.ofList)    
let l1   = NestedMap.Object ( List.zip ["Y"; "A"; "B"] [NestedMap.Value(1); l2'; l2''] |> Map.ofList)

这是我的代码:

let rec pruneWithKeyValue (keyvalue: string * int) (json: NestedMap) =
    let condition ck cv  = 
        let tgtKey = (fst keyvalue)
        let tgtVal = (snd keyvalue)
        match (ck, cv) with
        | (tgtKey, NestedMap.Value(tgtVal)) -> 
            printfn ">>> Found match : "
            printfn "       ck = %s    " ck 
            printfn "       tgtKey and tgtVal == %s, %i" tgtKey tgtVal
            true
        | _ -> false
    match json with
    | NestedMap.Object nmap -> 
        if (nmap |> Map.exists (fun k v -> condition k v)) then 
            json
        else
            printfn "Expanding w keyvalue: (%s,%i): " (fst keyvalue) (snd keyvalue)
            let expanded = nmap |> Map.map (fun k v -> pruneWithKeyValue keyvalue v) 
            NestedMap.Object(expanded |>  Map.filter (fun k v -> v <> NestedMap.Object (Map.empty)))  
    | _ -> NestedMap.Object (Map.empty)

let pruned = pruneWithKeyValue ("S",20) l1
let res = (pruned = l1)

结果不是所希望的:

>>> Found match : 
       ck = Y    
       tgtKey and tgtVal == Y, 1

val pruneWithKeyValue : string * int -> json:NestedMap -> NestedMap
val pruned : NestedMap =
  Object
    (map
       [("A", Object (map [("C", Value 10); ("D", Value 30); ("S", Value 20)]));
        ("B",
         Object
           (map
              [("G", Value 30);
               ("H",
                Object
                  (map [("E", Value 100); ("F", Value 300); ("S", Value 200)]));
               ("I", Value 40); ("S", Value 50)])); ("Y", Value 1)])
val remainsTheSame : bool = true

代码表示输出数据结构保持不变(val remainsTheSame : bool = true)。更有趣的是,不知何故,包含函数搜索的键值对的keyvalue元组被修改了:

>>> Found match : 
       ck = Y    
       tgtKey and tgtVal == Y, 1

这就是问题所在。事实上,如果我硬编码keyvalue元组:

let rec pruneWithKeyValue (keyvalue: string * int) (json: NestedMap) =
    let condition ck cv  = 
        let tgtKey = (fst keyvalue)
        let tgtVal = (snd keyvalue)
        match (ck, cv) with
        | ("S", NestedMap.Value(20)) -> 
            printfn ">>> Found match : "
            printfn "       ck = %s    " ck 
            printfn "       tgtKey and tgtVal == %s, %i" tgtKey tgtVal
            true
        | _ -> false
    match json with
    | NestedMap.Object nmap -> 
        if (nmap |> Map.exists (fun k v -> condition k v)) then 
            json
        else
            printfn "Expanding w keyvalue: (%s,%i): " (fst keyvalue) (snd keyvalue)
            let expanded = nmap |> Map.map (fun k v -> pruneWithKeyValue keyvalue v) 
            NestedMap.Object(expanded |>  Map.filter (fun k v -> v <> NestedMap.Object (Map.empty)))  
    | _ -> NestedMap.Object (Map.empty)

let pruned = pruneWithKeyValue ("S",20) l1
let remainsTheSame = (pruned = l1)

导致(是的)期望的结果:

Expanding w keyvalue: (S,20): 
>>> Found match : 
       ck = S    
       tgtKey and tgtVal == S, 20
Expanding w keyvalue: (S,20): 
Expanding w keyvalue: (S,20): 

val pruneWithKeyValue : string * int -> json:NestedMap -> NestedMap
val pruned : NestedMap =
  Object
    (map
       [("A", Object (map [("C", Value 10); ("D", Value 30); ("S", Value 20)]))])
val remainsTheSame : bool = false

这可能是微不足道的,但我不明白keyvalue最终会被修改的位置和方式,从而阻止我使用参数化键值元组获得正确的输出。

1 个答案:

答案 0 :(得分:3)

您无法与现有变量进行模式匹配,原始代码tgtKeytgtVal将成为新绑定,与现有变量无关。

所以改变你的比赛:

    match (ck, cv) with
    | (tgtKey, NestedMap.Value(tgtVal)) -> 

为:

    match (ck, cv) with
    | (k, NestedMap.Value v) when (k, v) = (tgtKey, tgtVal) -> 

或只是:

    match (ck, cv) with
    | x when x = (tgtKey, NestedMap.Value(tgtVal)) ->