#f# #dictionary #set #sequence
#f# #словарь #установить #последовательность
Вопрос:
Я написал следующий код, чтобы извлечь значения полей ID из последовательности словарей и вернуть их в виде набора — в основном я ищу значения PK для строк в таблице db, которую я использовал для заполнения словаря (1 dict на строку таблицы). Ниже кода приведены некоторые примеры данных, которые загружаются в последовательности словаря.
Хотя приведенный ниже код работает, стиль, вероятно, мог бы быть более функциональным — мне пришлось прибегнуть к использованию изменяемого списка для построения результирующего набора. Так что мне это кажется неправильным.
Кто-нибудь хочет предложить улучшенное, более функциональное решение здесь.
// Extract the PK values from a dictionary and create a key set from these data values
// The expected result here is: set ["PK1"; "PK2"; "PK3"; "PK4"]
let get_keyset (tseq:seq<Dictionary<string,string>>) =
let mutable setres =[]
for x in tseq do
for KeyValue(k,v) in x do
// Extract ID values/keys from each dict
setres <- x.Item("ID")::setres
setres |> List.rev |> Set.ofList
// Sample Data
// First Tuple is PK/ID value
let tabledata = [
[("ID", "PK1"); ("a2","aa"); ("a3", "aaa"); ("a4", "aaaa") ]
[("ID", "PK2"); ("b2","bb"); ("b3", "bbb"); ("b4", "bbbb") ]
[("ID", "PK3"); ("c2","cc"); ("c3", "ccc"); ("c4", "cccc") ]
[("ID", "PK4"); ("d2","dd"); ("d3", "ddd"); ("d4", "dddd") ]
]
//generate dict sequence from datasets
let gendictseq tabledata =
seq {
for tl in tabledata do
let ddict = new Dictionary<string,string>()
for (k,v) in tl do
ddict.Add(k,v)
yield ddict
}
Комментарии:
1. Если вы используете Set.ofList, зачем вам нужно перевернуть список?
Ответ №1:
Ваш get_keyset
выглядит довольно запутанным для меня. Это значительно более сжато:
let get_keyset tseq =
tseq |> Seq.map (fun (x:Dictionary<_,_>) -> x.["ID"]) |> set
Для gendictseq
я бы лично предпочел функции более высокого порядка выражению последовательности, но это в значительной степени вопрос вкуса:
let gendictseq tabledata =
tabledata
|> Seq.map (fun table ->
(Dictionary<_,_>(), table)
||> List.fold (fun dict keyValue -> dict.Add keyValue; dict))
Комментарии:
1. Согласен на повторную свертку в моем коде — вот почему я опубликовал. Ваши решения иллюстрируют реальную мощь подхода fp, где код действительно может быть сведен всего к нескольким кратким выражениям. (Я все еще изучаю этот материал — ваши примеры действительно помогают — Спасибо).
2. @BrendanC :
get_keyset
Можно было бы написать еще один интересный способ:let get_keyset : Dictionary<_,string> seq -> Set<_> = Seq.map (fun x -> x.["ID"]) >> set
:-]
Ответ №2:
Использование ResizeArray
( List<T>
в C #) лучше, чем изменяемая переменная списка:
let getKeyset (tseq:seq<Dictionary<string,string>>) =
let setres = new ResizeArray<string>()
for x in tseq do
for KeyValue(k,v) in x do
setres.Add(x.["ID"])
setres |> Set.ofSeq
или используйте более функциональное вычисление последовательности:
let getKeyset2 (tseq:seq<Dictionary<string,string>>) =
seq {
for x in tseq do
for KeyValue(k,v) in x do
yield x.["ID"]
}
|> Set.ofSeq
Комментарии:
1. Я бы сказал, что выражения последовательности менее функциональны и более обязательны…
Ответ №3:
Функционально эта операция представляет собой отображение, как показано ниже:
let get_keyset_new (tseq:seq<Dictionary<string,string>>) =
let s = tseq |> Seq.map (fun i -> i |> Seq.map (fun e -> i.Item("ID") ) )
seq {
for i in s do
yield! i
} |> Set.ofSeq