3

Learning f# using fparsec to parse some delimited data. I am using sepBy to get a list of results and filtering out the empty results. I don't want items that are empty but I do want to know what position the items were in. Is there a better way to get the index instead of List.mapi and later filtering out empties? The delimited data will have other delimited data inside (represents children).

type result = {value:string; index:int}
type parent = {results:result list; index:int}

let delims = "|^"

let pipeandcarrotdata = "|A^B^C||B|C"

let zipi res = List.mapi (fun i item -> res i item)
let zipPipes = zipi (fun i t -> {results = t; index = i})
let zipCarrots = zipi (fun i t -> {value = t; index = i})

let cleanlist predicate = List.filter (fun i -> predicate i)
let cleanPipes = cleanlist (fun t -> t.results.IsEmpty <> true)
let cleanCarrots = cleanlist (fun t -> t.value <> "")

let collect items = List.mapi (fun i item -> {value = item; index = i}) items
let cleanEmpties items = List.filter (fun item -> item.value <> "") items

let pCarrots = sepBy (manyChars (noneOf delims)) (pstring "^") |>> (zipCarrots >> cleanCarrots)
let pPipes = sepBy pCarrots (pstring "|") |>> (zipPipes >> cleanPipes)
test pPipes pipeandcarrotdata

Result:

[{results = [{value = "A";index = 0;}; {value = "B";index = 1;}; {value = "C";index = 2;}]; index = 1;}; 
{results = [{value = "B"; index = 0;}]; index = 3;}; 
{results = [{value = "C"; index = 0;}];index = 4;}]

Later I will need to support a more complex hierarchy and I would like to avoid writing 5-6 more functions like "cleanPipes" and "cleanCarrots" and then another 5-6 functions like "zipPipes" and "zipCarrots".

  • 1
    What criteria of "better" do you use when you ask for a "better way"? Or, in other words, what is the problem that you're trying to solve? – Fyodor Soikin Sep 19 '16 at 21:02
  • 1
    This might be better suited for [CodeReview](http://codereview.stackexchange.com/questions/tagged/f%23). Apart from that, I'd probably not define a separate type here and use: `let zipi = List.mapi (fun i item -> i, item); let clean = List.filter (snd >> (<>) "")` Note that `collect` is defined in e.g. the [List](https://msdn.microsoft.com/en-us/visualfsharpdocs/conceptual/list.collect%5B't,'u%5D-function-%5Bfsharp%5D) module with a different semantic already. – CaringDev Sep 19 '16 at 21:29
  • I edited my question, I hope that helps. @CaringDev I like your zipi suggestion, I'm really not used to thinking this way. I am a c# dev most of the time. – Joseph Evensen Sep 19 '16 at 22:30

0 Answers0