// This is the refactored version following comments by mjolka here: http://codereview.stackexchange.com/a/55606/4813
// Here are the "lines" from my "log file".
let lines = [1 .. 25] |> List.map (fun x -> x.ToString())
// For this exercise, section criteria is divisibility by 5.
// val DivisibleByFive : s:string -> bool
let DivisibleByFive (s:string) =
System.Int32.Parse(s) % 5 = 0
// I am going to use the following type to hold the information
// from each section of the log.
type Section (lines:string list) =
member x.Lines = lines
///
/// Splits the given sequence into non-empty contiguous subsequences, such
/// that the last element of every subsequence (except possibly the last)
/// satisfies the given predicate. No other elements satisfy the predicate.
///
///
///
/// let even x = x % 2 = 0
/// printfn "%A" (splitAtEach even (seq { 1 .. 3 }))
/// printfn "%A" (splitAtEach even (seq { 1 .. 4 }))
///
/// The output is:
///
/// seq [[1; 2]; [3]]
/// seq [[1; 2]; [3; 4]]
///
///
let splitAtEach (predicate : 'T -> bool) (xs : seq<'T>) : seq<'T list> =
let section = new ResizeArray<'T>()
seq {
for x in xs do
section.Add x
if predicate x then
yield Seq.toList section
section.Clear()
if section.Any() then
yield Seq.toList section
}
let sections =
splitAtEach DivisibleByFive lines
|> Seq.map (fun lines -> new Section(lines))
|> Seq.toList
printfn "Parsed %d section from the log:" sections.Length
sections |> List.iter (fun section -> printfn " Section starting with %s" section.Lines.[0])