【问题标题】:working on sequences with lagged operators使用滞后运算符处理序列
【发布时间】:2014-01-19 19:33:34
【问题描述】:

一台机器正在打开和关闭。 seqStartStop是一个seq<DateTime*DateTime>,收集机器任务执行的开始和结束时间。

我想生成机器空闲的时间序列。为此,我想构建一个元组序列(beginIdle, endIdle)

  • beginIdle 对应机器在运行过程中的停机时间 上一个周期。
  • endIdle 对应当前生产的开始时间 循环。

在实践中,我必须通过获取 i-1 元组的第二个元素和以下元组 i 的第一个元素来构建 (beginIdle, endIdle)

我想知道如何在不将 seqStartStop 转换为数组然后以命令式方式循环遍历数组的情况下完成这项任务。

另一个想法是创建两个seqStartStop 的副本:一个去除头部是尾部,一个去除头部(向后移动元素);然后应用map2。 我可以按照here 的描述使用skiptake

所有这些看起来都相当麻烦。有没有更直接的东西 一般来说,我想知道如何对序列中具有不同滞后的元素执行计算。

【问题讨论】:

  • 如何计算第一期的beginIdle和最后一期的endIdle
  • 或者空闲时间比机器运行时间少一个,这种情况下我们不用担心。
  • 好问题。是的,机器运行时的空闲时间更少。空闲时段是工作时段之间的时段。因此,空闲周期总是比工作周期数少一个。

标签: f# seq


【解决方案1】:

您可以使用Seq.pairwiseSeq.map 轻松实现这一点:

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

至于在具有不同滞后期的序列上执行的更一般的问题,您可以通过使用Seq.skipSeq.zip 来生成具有您需要的任何滞后期的组合序列。

【讨论】:

    【解决方案2】:

    map2 与序列的两个副本一起使用,其中一个通过取原始序列的尾部稍微移动,在函数式编程中是相当标准的想法,所以我会推荐这条路线。

    Seq.map2 函数适用于处理不同长度的列表 - 它只会在您到达较短列表的末尾时停止 - 因此您无需剪切原始副本的最后一个元素。

    需要注意的一点是原始seq&lt;DateTime*DateTime&gt; 的计算方式。每次枚举时都会重新计算,因此使用map2 的想法会计算两次。如果计算成本低且不涉及副作用,那很好。否则,先用List.ofSeq将其转换为列表。

    您仍然可以在列表上使用Seq.map2,因为列表是IEnumerable(即seq)。不要使用List.map2,除非列表长度相同,但它比Seq.map2 更挑剔。

    【讨论】:

    • 感谢您的概述。我想我会使用序列的两个移位副本。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-01
    • 2013-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多