我有一个稀疏的时间戳列表,让我们把它简化为:
val stamps = List(1,2,3,7,10,11)
想象一下,我的窗口大小为3,Scala / Functional方法可以获得以下输出
valueWindowed (3, stamps) == List(
// Starting at timestamp 1 of stamps, we include the next values which are no bigger than the current value + the window size
List(1, 2, 3),
// Starting at timestamp 2 include the next values in this window
List(2, 3),
List(3), // ...
// This one is empty as the window starts at timestamp 4 and ends at 6 (inclusive)
List(),
// This one _does_ include 7, as the windows starts at 5 and ends at 7 (inclusive)
List(7),
List(7),
List(7),
List(10),
List(10,11),
List(10,11),
List(11)
)
我有以下实现,但它看起来非常程序化,卡在功能结构中。复杂性也是max(stamps) * stamps size
def valueWindowed(step: Int, times: List[Int]) = {
for(j <- (1 to times.max).toIterator) yield{
times.dropWhile(_ < j) takeWhile(_ < j+step)
}
}
答案 0 :(得分:1)
这是一个功能性的O(N) - 其中N是times
中数字的范围,而不是它的长度。但是,由于这是你输出的大小,所以不可能做得更好。
def valueWindowed(step:Int, times:List[Int]) = {
(times :+ times.last+step)
.sliding(2)
.flatMap{case List(a,b) => Some(a)::List.fill(b-a-1)(None)}
.sliding(step)
.map(_.flatten)
}
第一个sliding
和flatMap
展开列表,使其Some(x)
中的所有x都为times
,所有中间值为None
(添加sentinel值以正确包含最后一个元素)。然后我们使用steps
个窗口并使用flatten
删除None
/转换Some
返回