Map.ofSeq具有重复键的行为是什么?

时间:2018-06-11 18:32:28

标签: f#

当同一个密钥出现两次时Map.ofSeq的行为是什么?

docs没有提到这个案例。

2 个答案:

答案 0 :(得分:7)

让我们凭经验测试一下......

这个例子:

[("key", 1); ("key", 2); ("key", 3)] |> Map.ofSeq

产生以下结果:

map [("key", 3)]

这个例子:

[("key", 3); ("key", 1);] |> Map.ofSeq

给出了这个结果:

map [("key", 1)]

因此,当有重复时,似乎Map.ofSeq使用给定键的序列中的最后一个条目。

修改

正如Fyodor Soikin指出的那样,您不会希望依赖代码中的未记录行为。因此,如果要在序列中存在多个具有相同键的值时确保选择给定值的特定行为,则可以使用如下函数:

module Map =
    let ofSeqWithDuplicates<'key,'value when 'key : comparison> (resolver: 'key -> 'value seq -> 'value) seq =
        let rec getDuplicates state remaining = 
            match remaining |> Seq.tryHead with
            | Some (key, value) -> 
                let newItem = Seq.singleton value
                let newState =                     
                    match state |> Map.tryFind key with
                    | Some existing -> state |> Map.add key (existing |> Seq.append newItem)
                    | None -> state |> Map.add key newItem
                remaining |> Seq.tail |> getDuplicates newState
            | None -> state

        seq
        |> getDuplicates Map.empty<'key, 'value seq>
        |> Map.map (fun key values -> values |> resolver key)

这允许您传递一个名为resolver的函数,该函数从给定键的重复值列表中选择值。当我们使用上面的第一个例子时,我们可以明确地选择最小值,如下所示:

[("key", 1); ("key", 2); ("key", 3)] 
|> Map.ofSeqWithDuplicates (fun key values -> values |> Seq.min)

现在我们得到地图:

map [("key", 1)]

答案 1 :(得分:7)

source code表示序列中Map的构造是通过多次调用add实现的,按照源集合的顺序执行,从而产生语义“最后写作获胜“。

但是,由于文档没有提及此属性,因此在生产代码中依赖是不明智的。就目前而言,此行为是内部实现细节,可能会在标准库的后续版本中发生更改。