我在Haskell中实现了一个count
函数,我想知道这会在大型列表上表现得很糟糕:
count :: Eq a => a -> [a] -> Int
count x = length . filter (==x)
我相信length
函数在线性时间内运行,这是正确的吗?
编辑:@Higemaru建议的重构
答案 0 :(得分:9)
长度以线性时间运行到列表大小,是的。
通常,您会担心您的代码必须在列表中进行两次传递:第一次过滤,然后一次计算结果列表的长度。但是,我相信这不会发生在这里,因为过滤器对列表的结构并不严格。相反,长度函数在它过程中强制过滤列表的元素,在一次传递中执行实际计数。
答案 1 :(得分:4)
我认为你可以稍微缩短一下
count :: Eq a => a -> [a] -> Int
count x = length . filter (x==)
(如果可以的话,我会写一篇(低评论)
答案 2 :(得分:0)
这真的取决于清单。对于我计算机上Int
的正常,懒惰评估列表,我看到这个函数在10 ^ 9个元素中运行大约2秒,10 ^ 8运行0.2秒,10 ^ 7运行0.3秒,所以它似乎以线性时间运行。您可以在命令行运行时将标志+RTS -s -RTS
传递给可执行文件,从而自行检查。
我也尝试使用更多内核运行它,但它似乎没有做任何事情,只是稍微增加了内存使用量。
懒惰计算的另一个好处是你只能在列表上进行一次传递。 filter
和length
由编译器转换为单个循环(打开优化),因此可以节省内存和效率。