Grouping striped data

This is a text file in which the keys and values ​​are in alternating order, for example:

KeyA
ValueA
KeyB
ValueB
KeyC
ValueC
...

I would like to create a dictionary / hash table from this data. How do I go about it with a functional manner?

+3
source share
5 answers

I would do something like this, although I'm not sure if this is the most “functional” approach:

let dic = Dictionary<string,string>()
File.ReadAllLines(@"keyvalue.txt")
|> Seq.pairwise
|> Seq.iteri( fun i (a,b)-> if i % 2 = 0 then dic.Add(a,b))
+3
source

@BrokenGlass was right on a ball recognizing Seq.pairwiseas the perfect fit for retrieving your data. But for a more functional solution, use immutable Microsoft.FSharp.Collections.Mapinstead of 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

And if your data file is huge, consider reading the values ​​as a stream for better performance:

seq { 
    use sr = System.IO.File.OpenText @"keyvalue.txt"
    while(not sr.EndOfStream) do yield (sr.ReadLine(), sr.ReadLine())
}
|> Map.ofSeq
+6

, , , . , , 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

, iter - , , F # seq. - iter.

+5
let loadFile path =
    let rec loop acc = function
    | k::v::rest -> loop ((k, v)::acc) rest
    | []         -> dict acc
    | _          -> failwith "odd number of lines"

    path |> System.IO.File.ReadAllLines |> List.ofArray |> loop []
+2
source

Split it into a list of strings, use List.choose or Seq.choose to split it into odd / even lists, and then maybe use List.zip in these two lists. insert them into the list of key / value tuples.

0
source

Source: https://habr.com/ru/post/1794981/


All Articles