在 Haskell 中实现高效的滑动窗口算法 [英] Implementing an efficient sliding-window algorithm in Haskell

查看:27
本文介绍了在 Haskell 中实现高效的滑动窗口算法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 Haskell 中需要一个高效的滑动窗口函数,所以我写了以下内容:

I needed an efficient sliding window function in Haskell, so I wrote the following:

windows n xz@(x:xs)
  | length v < n = []
  | otherwise = v : windows n xs
  where
    v = take n xz

我的问题是我认为复杂度是 O(n*m),其中 m 是列表的长度,n 是窗口大小.你对 take 的列表倒数一次,length 再倒数一次,然后你在列表中向下倒数 m-n 次.似乎它可以比这更有效,但我不知道如何使它更线性.有吃货吗?

My problem with this is that I think the complexity is O(n*m) where m is the length of the list and n is the window size. You count down the list once for take, another time for length, and you do it down the list of essentially m-n times. It seems like it can be more efficient than this, but I'm at a loss for how to make it more linear. Any takers?

推荐答案

没有比 O(m*n) 更好的了,因为这是输出数据结构的大小.

You can't get better than O(m*n), since this is the size of the output data structure.

但是,如果您颠倒操作顺序,则可以避免检查窗口的长度:首先创建 n 个移位列表,然后将它们压缩在一起.压缩将自动摆脱那些没有足够元素的元素.

But you can avoid checking the lengths of the windows if you reverse the order of operations: First create n shifted lists and then just zip them together. Zipping will get rid of those that don't have enough elements automatically.

import Control.Applicative
import Data.Traversable (sequenceA)
import Data.List (tails)

transpose' :: [[a]] -> [[a]]
transpose' = getZipList . sequenceA . map ZipList

压缩列表列表只是一个转置,但与transpose不同code> 来自 Data.List 它会丢弃少于 n 个元素的输出.

Zipping a list of lists is just a transposition, but unlike transpose from Data.List it throws away outputs that would have less than n elements.

现在很容易制作窗口函数:取 m 个列表,每个列表移动 1,然后压缩它们:

Now it's easy to make the window function: Take m lists, each shifted by 1, and just zip them:

windows :: Int -> [a] -> [[a]]
windows m = transpose' . take m . tails

也适用于无限列表.

这篇关于在 Haskell 中实现高效的滑动窗口算法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆