基于值(不是索引)的滑动窗口

时间:2016-03-11 10:22:00

标签: scala

我有一个稀疏的时间戳列表,让我们把它简化为:

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)
  }
}

1 个答案:

答案 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)
}

第一个slidingflatMap展开列表,使其Some(x)中的所有x都为times,所有中间值为None(添加sentinel值以正确包含最后一个元素)。然后我们使用steps个窗口并使用flatten删除None /转换Some返回