Каково поведение Map.ofSeq с дублирующимися ключами? - PullRequest
0 голосов
/ 11 июня 2018

Каково поведение Map.ofSeq, когда один и тот же ключ встречается дважды?

В документах этот случай не упоминается.

Ответы [ 2 ]

0 голосов
/ 11 июня 2018

Исходный код указывает, что построение Map из последовательности достигается с помощью нескольких вызовов add, выполненных в порядке сбора источника, что приводит кв семантике «последняя запись выигрывает».

Однако, поскольку в документации не упоминается это свойство, было бы неразумно полагаться на него в рабочем коде.В данном случае это поведение является внутренней деталью реализации и может измениться в следующей версии стандартной библиотеки.

0 голосов
/ 11 июня 2018

Давайте проверим это эмпирически и выясним ...

Этот пример:

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

Создает следующий результат:

map [("key", 3)]

В то время как этот пример:

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

Дает этот результат:

map [("key", 1)]

Следовательно, Map.ofSeq использует последнюю запись в последовательности с данным ключом при наличии дубликатов.

РЕДАКТИРОВАТЬ

Как отметил Федор Сойкин, вы не захотите полагаться на недокументированное поведение в своем коде.Поэтому, если вы хотите обеспечить определенное поведение для выбора заданного значения, когда в последовательности есть несколько значений с одним и тем же ключом, вы можете использовать функцию, подобную следующей:

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)]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...