fjd*_*ont 3 f# grouping functional-programming hashtable
给定是一个文本文件,其中键和值按交替顺序排列,如下所示:
KeyA
ValueA
KeyB
ValueB
KeyC
ValueC
...
Run Code Online (Sandbox Code Playgroud)
我想从该数据创建一个字典/哈希表.我将如何以功能性方式实现这一目标?
@BrokenGlass是正确的球,认为Seq.pairwise它是提取数据的最佳选择.但是对于更实用的解决方案,请使用immutable Microsoft.FSharp.Collections.Map而不是mutable System.Collections.Generic.Dictionary:
System.IO.File.ReadAllLines @"keyvalue.txt"
|> Seq.pairwise
|> Seq.mapi (fun i x -> if i % 2 = 0 then Some(x) else None)
|> Seq.choose id
|> Map.ofSeq
Run Code Online (Sandbox Code Playgroud)
如果您的数据文件很大,请考虑将值作为流读取,以获得更好的性能:
seq {
use sr = System.IO.File.OpenText @"keyvalue.txt"
while(not sr.EndOfStream) do yield (sr.ReadLine(), sr.ReadLine())
}
|> Map.ofSeq
Run Code Online (Sandbox Code Playgroud)
我认为之前发布的所有答案都给出了很好的解决方案.有趣的是,这不是使用F#序列表达式可以优雅地解决的问题 - 您必须使用列表和递归,一些棘手的函数(例如pairwise)或使用IEnumerator接口.
我写了一个允许你使用的计算构建器IEnumerator(参见fssnip.net上的完整源代码).使用这个计算,你可以非常好地解决它:
let loadFile path =
// Recursive function that generates IEnumerator of key * value pairs
let rec loop source = iter {
// Read key & value and continue if both are available
let! key = source
let! value = source
match key, value with
| Some key, Some value ->
// Produce key * value pair and continue looping
yield key, value
yield! loop source
| _ -> () }
// Create sequence that reads data and convert it to dictionary
Enumerator.toSeq (fun () ->
loop (File.ReadAllLines(@"keyvalue.txt").GetEnumerator())) |> dict
Run Code Online (Sandbox Code Playgroud)
我发现iter计算非常好 - 在某些情况下你无法用F#解决问题seq.然后你可以使用递归和列表 - 但是同样的递归模式也可以使用非常整齐地编写iter.