背景:我有一系列连续的,带时间戳的数据.数据序列中有孔,有些大,有些只有一个缺失值.
每当孔只是一个缺失值时,我想使用虚拟值修补孔(较大的孔将被忽略).
我想使用延迟生成修补序列,因此我使用Seq.unfold.
我已经制作了两个版本的方法来修补数据中的漏洞.
第一个消耗带有孔的数据序列并产生修补序列.这就是我想要的,但是当输入序列中的元素数量超过1000时,方法运行得非常慢,并且输入序列包含的元素越多,它就会越来越差.
第二种方法使用带有孔的数据列表并生成修补序列并且运行速度很快.然而,这不是我想要的,因为这会强制整个输入列表在内存中的实例化.
我想使用(sequence - > sequence)方法而不是(list - > sequence)方法,以避免在内存中同时存在整个输入列表.
问题:
1)为什么第一种方法如此缓慢(使用较大的输入列表逐渐变得更糟)(我怀疑它与使用Seq.skip 1重复创建新序列有关,但我不确定)
2)如何使用输入序列而不是输入列表快速修补数据中的空洞?
代码:
open System
// Method 1 (Slow)
let insertDummyValuesWhereASingleValueIsMissing1 (timeBetweenContiguousValues : TimeSpan) (values : seq<(DateTime * float)>) =
let sizeOfHolesToPatch = timeBetweenContiguousValues.Add timeBetweenContiguousValues // Only insert dummy-values when the gap is twice the normal
(None, values) |> Seq.unfold (fun (prevValue, restOfValues) ->
if restOfValues |> Seq.isEmpty then
None // Reached the …Run Code Online (Sandbox Code Playgroud) 这是我一直在努力解决的问题.我需要将两个排序的序列合并为一个排序的序列.理想情况下,算法应该是惰性求值的,并且不需要从每个序列中缓存多个项目.这不是一个非常难以解决的问题,我已经能够在F#中设计出许多解决方案.不幸的是,我提出的每个解决方案都存在一些问题.
使用yield!对子序列生成器的递归调用.这会产生优雅的外观解决方案,但为每个项目创建子序列都是性能杀手.
真正神秘且无法维护的代码,包含深度堆叠的匹配开关,多个几乎完全相同的代码块等.
强制F#进入纯粹程序模式的代码(许多可变值等).
所有在线示例我都能在同一个浅滩上找到创始人.
我错过了一些明显的东西:比如它真的很简单还是显然不可能?有谁知道一个非常优雅的解决方案,也是高效的,大部分功能?(它不必是纯功能性的.)如果不是,我最终可能缓存子序列,并使用列表或阵列.
有用于产生汉明数的无限流(即所有的正整数公知的解决方案n,其中n = 2^i * 3^j * 5^k).我在F#中以两种不同的方式实现了这一点.第一种方法使用seq<int>.解决方案很优雅,但性能很糟糕.第二种方法使用尾部被包裹的自定义类型Lazy<LazyList<int>>.解决方案很笨重,但性能却令人惊叹.
有人可以解释为什么性能使用seq<int>如此糟糕,如果有办法解决它?谢谢.
方法1使用seq<int>.
// 2-way merge with deduplication
let rec (-|-) (xs: seq<int>) (ys: seq<int>) =
let x = Seq.head xs
let y = Seq.head ys
let xstl = Seq.skip 1 xs
let ystl = Seq.skip 1 ys
if x < y then seq { yield x; yield! xstl -|- ys }
elif x > y then seq { yield y; yield! …Run Code Online (Sandbox Code Playgroud)