- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在阅读了冈崎的纯函数式数据结构中关于持久性的文章并浏览了他关于单链表的说明性示例(这就是 Haskell 列表的实现方式)后,我好奇 Data.List
的 inits
和 tails
的空间复杂度...
在我看来
tails
的空间复杂度与其参数的长度呈线性关系,并且inits
的空间复杂度是其参数长度的二次,但一个简单的基准测试表明情况并非如此。
使用tails
,可以共享原始列表。计算 tails xs
只需沿着列表 xs
遍历并创建一个指向该列表中每个元素的新指针即可;无需在内存中重新创建部分 xs
。
相反,由于 inits xs
的每个元素“以不同的方式结束”,因此不可能存在这种共享,并且 xs
的所有可能的前缀都必须是在内存中从头开始重新创建。
下面的简单基准测试显示两个函数之间的内存分配没有太大差异:
-- Main.hs
import Data.List (inits, tails)
main = do
let intRange = [1 .. 10 ^ 4] :: [Int]
print $ sum intRange
print $ fInits intRange
print $ fTails intRange
fInits :: [Int] -> Int
fInits = sum . map sum . inits
fTails :: [Int] -> Int
fTails = sum . map sum . tails
编译我的 Main.hs
文件后
ghc -prof -fprof-auto -O2 -rtsopts Main.hs
正在运行
./Main +RTS -p
Main.prof
文件报告以下内容:
COST CENTRE MODULE %time %alloc
fInits Main 60.1 64.9
fTails Main 39.9 35.0
为fInits
分配的内存和为fTails
分配的内存具有相同的数量级...嗯...
tails
(线性)和 inits
(二次)空间复杂度的结论正确吗?fInits
和 fTails
分配大致相同的内存? 列表融合与此有关吗?最佳答案
Haskell 报告中 inits
的实现与基本 4.7.0.1 (GHC 7.8.3) 之前使用的实现相同或几乎相同,但速度非常慢。特别是,fmap
应用程序递归地堆叠,因此强制结果的连续元素变得越来越慢。
inits [1,2,3,4] = [] : fmap (1:) (inits [2,3,4])
= [] : fmap (1:) ([] : fmap (2:) (inits [3,4]))
= [] : [1] : fmap (1:) (fmap (2:) ([] : fmap (3:) (inits [4])))
....
Bertram Felgenhauer 探索的最简单的渐近最优实现基于应用 take
和连续更大的参数:
inits xs = [] : go (1 :: Int) xs where
go !l (_:ls) = take l xs : go (l+1) ls
go _ [] = []
Felgenhauer 能够使用私有(private)的、非融合版本的 take
来获得一些额外的性能,但它仍然没有达到应有的速度。
以下非常简单的实现在大多数情况下速度明显更快:
inits = map reverse . scanl (flip (:)) []
在一些奇怪的极端情况下(例如map head.inits
),这个简单的实现渐近非最优。因此,我使用相同的技术编写了一个版本,但基于 Chris Okasaki 的银行家队列,它既是渐近最优的,又几乎一样快。 Joachim Breitner 对其进行了进一步优化,主要是使用严格的 scanl'
而不是通常的 scanl
,并且此实现进入了 GHC 7.8.4。 inits
现在可以在 O(n) 时间内生成结果的主干;强制整个结果需要 O(n^2) 时间,因为没有任何 conses 可以在不同的初始段之间共享。如果您想要非常快的 inits
和 tails
,最好的选择是使用 Data.Sequence
; Louis Wasserman 的实现 is magical 。另一种可能性是使用 Data.Vector - 它可能使用切片来实现此类操作。
关于haskell - init 和 tail 的空间复杂度是多少?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29393412/
我有一个日志文件,想要创建一个网页(可能是Python,但不是严格意义上),该网页的工作方式类似于Unix的“tail -f filename”命令的工作方式(将新的日志行写入文件时显示)。 这样,该
当我为日志文件运行 tail -f 时,logrotate 旋转它但 tail -f 没有停止。它继续在新文件中显示日志。之后我手动尝试; mv my.log my.log.2 touch my.lo
您将如何在 bash 中实现这一点。这是我在面试中被问到的一个问题,我可以想到高级语言的答案,而不是 shell。 据我了解,tail 的真正实现是查找文件末尾,然后向后读取。 最佳答案 主要思想是保
例如: NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"hello: (.*)ABC"
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题吗? Update the question所以它是on-topic用于堆栈溢出。 关闭 9 年前。 Improve this
为什么我不能tail tail 的结果?我可以调用head在序列 tail返回(和其他变体),但 tail在 tail不起作用(在 2017.10 中): > my $list = ; (a b c
A previous question如何讨论 Haskell 表达式的类型 ap zip tail可以翻译成\x -> zip x (tail x)的类型.这很有启发性,但是那里的问题和答案都没有涉
因为我试图保持容器运行,所以我在 docker compose 文件中将“tail -f/dev/null”指定为 command: version: '2' services: serviceN
以下是为拖尾“n”行文件编写的代码。 import java.io.RandomAccessFile; import java.util.HashMap; import java.util.Map
我有一个递归方案样式结构,我想获得所有子结构的列表,包括完整结构 - 即相当于 tails函数在 List 上执行.我认为可以通过调用 para 来实现这一点。 ,在每一步映射回原始结构,然后分别将原
编辑 这是一个 JSFiddle,其中注释掉了“tail”函数的代码。 Solar System JSFiddle 我有一个我正在研究的物体,它有一个围绕中心质量运行的物体。这非常有效。 我现在正尝试
我想跟踪一个文件,但 tail -f 始终从最后 10 行开始。有没有办法输出整个文件然后遵循? 我的目标是查找日志中出现的所有字符串,例如 tail -f Streaming_log | grep“
我试图在我的循环单向链表中将两端连接在一起。在文件名 file.txt 中,包含 ABCDEFGHIJKLMNOPQRSTUVWXYZ 作为文本,我能够分别打印出头部和尾部 A 和 Z。但是,我希望
我目前遇到命令问题 while sleep 0.3; do echo "1"; done | tail -n +3 | grep --line-buffered "1" 我想要一个看起来像这样的输出:
所以我想稍微了解一下 Linux 脚本,并从书中的一个简单示例开始。在这本书中,作者要我从 snort.conf 中获取“第 6 步:配置输出插件”之前的五行。 类似于作者,我确定了我想要的行的位置,
我想跟踪一个将不间断写入的日志文件,问题是在我的脚本中我不想指定行数或字节数等。要跟踪,我想在我的脚本中指定每次跟踪之前未跟踪的最后一行。我怎样才能在我的脚本中做到这一点?谢谢 最佳答案 我认为 20
Problem: Program to read the lines from infinite stream starting from its end of file. #解决方案: import
我想安装 Linux Tails。我已经将 ppa:tails-team/tails-installer 添加到我的源中,但是当我的 Ubuntu 软件中心尝试下载存储库信息时,我收到此错误: W:F
读取记录时间序列数据的 1 GB 文件并生成包含两列(一列时间,另一列数字)的实时图表的最佳方法是什么?我看到您有不同的方式来调整文件。 最佳答案 对于 RRDTool 来说听起来不错. 但如果您想坚
需要监视日志文件中的特定字符串“Server running at http”。在日志文件中找到该字符串后,我需要停止检查并想继续其余代码。 目前我正在使用 "tail -f my-file.log
我是一名优秀的程序员,十分优秀!