Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Below is some code that does what I think you want. It is not idiomatic F#. </p> <p>(It may be similar to Brian's answer, though I can't tell because I'm not familiar with the LazyList semantics.)</p> <p>But it doesn't exactly match your test specification: Seq.length enumerates its entire input. Your "test code" calls <code>Seq.length</code> and then calls <code>Seq.hd</code>. That will generate an enumerator twice, and since there is no caching, things get messed up. I'm not sure if there is any clean way to allow multiple enumerators without caching. Frankly, <code>seq&lt;seq&lt;'a&gt;&gt;</code> may not be the best data structure for this problem. </p> <p>Anyway, here's the code:</p> <pre><code>type State&lt;'a&gt; = Unstarted | InnerOkay of 'a | NeedNewInner of 'a | Finished // f() = true means the neighbors should be kept together // f() = false means they should be split let split_up (f : 'a -&gt; 'a -&gt; bool) (input : seq&lt;'a&gt;) = // simple unfold that assumes f captured a mutable variable let iter f = Seq.unfold (fun _ -&gt; match f() with | Some(x) -&gt; Some(x,()) | None -&gt; None) () seq { let state = ref (Unstarted) use ie = input.GetEnumerator() let innerMoveNext() = match !state with | Unstarted -&gt; if ie.MoveNext() then let cur = ie.Current state := InnerOkay(cur); Some(cur) else state := Finished; None | InnerOkay(last) -&gt; if ie.MoveNext() then let cur = ie.Current if f last cur then state := InnerOkay(cur); Some(cur) else state := NeedNewInner(cur); None else state := Finished; None | NeedNewInner(last) -&gt; state := InnerOkay(last); Some(last) | Finished -&gt; None let outerMoveNext() = match !state with | Unstarted | NeedNewInner(_) -&gt; Some(iter innerMoveNext) | InnerOkay(_) -&gt; failwith "Move to next inner seq when current is active: undefined behavior." | Finished -&gt; None yield! iter outerMoveNext } open System let groupContigs (contigTime : TimeSpan) (holey : seq&lt;DateTime * int&gt;) = split_up (fun (t1,_) (t2,_) -&gt; (t2 - t1) &lt;= contigTime) holey // Test data let numbers = {1 .. 15} let contiguousTimeStamps = let baseTime = DateTime.Now seq { for n in numbers -&gt; baseTime.AddMinutes(float n)} let holeyData = Seq.zip contiguousTimeStamps numbers |&gt; Seq.filter (fun (dateTime, num) -&gt; num % 7 &lt;&gt; 0) let grouped_data = groupContigs (new TimeSpan(0,1,0)) holeyData printfn "Consuming..." for group in grouped_data do printfn "about to do a group" for x in group do printfn " %A" x </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload