3 people like it.
Like the snippet!
Group elements of a sequence by time windows of fixed intervals
Function that associates a time window with each element of a sequence. The resulting sequence can then be grouped by the time windows for further processing
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
|
open System
let withTimeWindow<'T> (fnTime:'T-> DateTime) (window:TimeSpan) (xs:'T seq) =
let xs' = xs |> Seq.sortBy fnTime
let tFrom = xs' |> Seq.head |> fnTime
let tTo = tFrom.AddSeconds(window.TotalSeconds)
let ixs = xs'.GetEnumerator()
let rec nxt(f:DateTime,t) prevX =
seq {
let x =
prevX
|> Option.map(fun _ -> prevX)
|> Option.defaultWith(fun () -> if ixs.MoveNext() then Some(ixs.Current) else None)
match x with
| Some x ->
let tx = fnTime x
if tx < t then
yield ((f,t),x)
yield! nxt (f,t) None
else
let f = f.AddSeconds(window.TotalSeconds)
let t = t.AddSeconds(window.TotalSeconds)
yield! nxt (f,t) (Some x)
| None -> ixs.Dispose()
}
nxt (tFrom,tTo) None
(*
let xs = seq{for i in 0 .. 100 -> i } |> Seq.scan (fun ((s:DateTime),_) t -> s.AddMinutes(1.0),t) (DateTime.Now,0)
let wxs = xs |> withTimeWindow fst (TimeSpan.FromMinutes 5.)
let wsg = wxs |> Seq.groupBy fst |> Seq.map (fun (interval,xs)->interval,Seq.length xs) |> Seq.toArray
>
val wsg : ((DateTime * DateTime) * int) [] =
[|((8/26/2020 4:36:01 PM, 8/26/2020 4:41:01 PM), 5);
((8/26/2020 4:41:01 PM, 8/26/2020 4:46:01 PM), 5);
((8/26/2020 4:46:01 PM, 8/26/2020 4:51:01 PM), 5);
((8/26/2020 4:51:01 PM, 8/26/2020 4:56:01 PM), 5);
((8/26/2020 4:56:01 PM, 8/26/2020 5:01:01 PM), 5);
((8/26/2020 5:01:01 PM, 8/26/2020 5:06:01 PM), 5);
((8/26/2020 5:06:01 PM, 8/26/2020 5:11:01 PM), 5);
((8/26/2020 5:11:01 PM, 8/26/2020 5:16:01 PM), 5);
((8/26/2020 5:16:01 PM, 8/26/2020 5:21:01 PM), 5);
((8/26/2020 5:21:01 PM, 8/26/2020 5:26:01 PM), 5);
((8/26/2020 5:26:01 PM, 8/26/2020 5:31:01 PM), 5);
((8/26/2020 5:31:01 PM, 8/26/2020 5:36:01 PM), 5);
((8/26/2020 5:36:01 PM, 8/26/2020 5:41:01 PM), 5);
((8/26/2020 5:41:01 PM, 8/26/2020 5:46:01 PM), 5);
((8/26/2020 5:46:01 PM, 8/26/2020 5:51:01 PM), 5);
((8/26/2020 5:51:01 PM, 8/26/2020 5:56:01 PM), 5);
((8/26/2020 5:56:01 PM, 8/26/2020 6:01:01 PM), 5);
((8/26/2020 6:01:01 PM, 8/26/2020 6:06:01 PM), 5);
((8/26/2020 6:06:01 PM, 8/26/2020 6:11:01 PM), 5);
((8/26/2020 6:11:01 PM, 8/26/2020 6:16:01 PM), 5);
((8/26/2020 6:16:01 PM, 8/26/2020 6:21:01 PM), 2)|]
*)
|
namespace System
val withTimeWindow : fnTime:('T -> DateTime) -> window:TimeSpan -> xs:seq<'T> -> seq<(DateTime * DateTime) * 'T>
val fnTime : ('T -> DateTime)
Multiple items
type DateTime =
struct
new : ticks:int64 -> DateTime + 10 overloads
member Add : value:TimeSpan -> DateTime
member AddDays : value:float -> DateTime
member AddHours : value:float -> DateTime
member AddMilliseconds : value:float -> DateTime
member AddMinutes : value:float -> DateTime
member AddMonths : months:int -> DateTime
member AddSeconds : value:float -> DateTime
member AddTicks : value:int64 -> DateTime
member AddYears : value:int -> DateTime
...
end
--------------------
DateTime ()
(+0 other overloads)
DateTime(ticks: int64) : DateTime
(+0 other overloads)
DateTime(ticks: int64, kind: DateTimeKind) : DateTime
(+0 other overloads)
DateTime(year: int, month: int, day: int) : DateTime
(+0 other overloads)
DateTime(year: int, month: int, day: int, calendar: Globalization.Calendar) : DateTime
(+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int) : DateTime
(+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, kind: DateTimeKind) : DateTime
(+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, calendar: Globalization.Calendar) : DateTime
(+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, millisecond: int) : DateTime
(+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, millisecond: int, kind: DateTimeKind) : DateTime
(+0 other overloads)
val window : TimeSpan
Multiple items
type TimeSpan =
struct
new : ticks:int64 -> TimeSpan + 3 overloads
member Add : ts:TimeSpan -> TimeSpan
member CompareTo : value:obj -> int + 1 overload
member Days : int
member Divide : divisor:float -> TimeSpan + 1 overload
member Duration : unit -> TimeSpan
member Equals : value:obj -> bool + 1 overload
member GetHashCode : unit -> int
member Hours : int
member Milliseconds : int
...
end
--------------------
TimeSpan ()
TimeSpan(ticks: int64) : TimeSpan
TimeSpan(hours: int, minutes: int, seconds: int) : TimeSpan
TimeSpan(days: int, hours: int, minutes: int, seconds: int) : TimeSpan
TimeSpan(days: int, hours: int, minutes: int, seconds: int, milliseconds: int) : TimeSpan
val xs : seq<'T>
Multiple items
val seq : sequence:seq<'T> -> seq<'T>
--------------------
type seq<'T> = Collections.Generic.IEnumerable<'T>
val xs' : seq<'T>
module Seq
from Microsoft.FSharp.Collections
val sortBy : projection:('T -> 'Key) -> source:seq<'T> -> seq<'T> (requires comparison)
val tFrom : DateTime
val head : source:seq<'T> -> 'T
val tTo : DateTime
val ixs : Collections.Generic.IEnumerator<'T>
val nxt : (DateTime * DateTime -> 'T option -> seq<(DateTime * DateTime) * 'T>)
val f : DateTime
val t : DateTime
val prevX : 'T option
val x : 'T option
module Option
from Microsoft.FSharp.Core
val map : mapping:('T -> 'U) -> option:'T option -> 'U option
val defaultWith : defThunk:(unit -> 'T) -> option:'T option -> 'T
union case Option.Some: Value: 'T -> Option<'T>
union case Option.None: Option<'T>
val x : 'T
val tx : DateTime
More information