문제

A machine is turning on and off. seqStartStop is a seq<DateTime*DateTime> that collects the start and end time of the execution of the machine tasks.

I would like to produce the sequence of periods where the machine is idle. In order to do so, I would like to build a sequence of tuples (beginIdle, endIdle).

  • beginIdle corresponds to the stopping time of the machine during the previous cycle.
  • endIdle corresponds to the start time of the current production cycle.

In practice, I have to build (beginIdle, endIdle) by taking the second element of the tuple for i-1 and the fist element of the following tuple i

I was wondering how I could get this task done without converting seqStartStop to an array and then looping through the array in an imperative fashion.

Another idea creating two copies of seqStartStop: one where the head is tail is removed, one where the head is removed (shifting backwards the elements); and then appying map2. I could use skipand take as described here

All these seem rather cumbersome. Is there something more straightforward In general, I was wondering how to execute calculations on elements with different lags in a sequence.

도움이 되었습니까?

해결책

You can implement this pretty easily with Seq.pairwise and Seq.map:

let idleTimes (startStopTimes : seq<DateTime * DateTime>) =
    startStopTimes
    |> Seq.pairwise
    |> Seq.map (fun (_, stop) (start, _) ->
        stop, start)

As for the more general question of executing on sequences with different lag periods, you could implement that by using Seq.skip and Seq.zip to produce a combined sequence with whatever lag period you require.

다른 팁

The idea of using map2 with two copies of the sequence, one slightly shifted by taking the tail of the original sequence, is quite a standard one in functional programming, so I would recommend that route.

The Seq.map2 function is fine with working with lists with different lengths - it just stops when you reach the end of the shorter list - so you don't need to chop the last element of the original copy.

One thing to be careful of is how your original seq<DateTime*DateTime> is calculated. It will be recalculated each time it is enumerated, so with the map2 idea it will be calculated twice. If it's cheap to calculate and doesn't involve side-effects, this is fine. Otherwise, convert it to a list first with List.ofSeq.

You can still use Seq.map2 on lists as a list is an IEnumerable (i.e. a seq). Don't use List.map2 unless the lists are the same length though as it is more picky than Seq.map2.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top