我有一个.dat文件,其中包含某些数据(文本、数字等)。该数据文件的结构以信息块的形式出现,以包含短语“修补程序n”的一行开头,n是块的编号:
patch 0
-----
-----
patch 1
-----
-----
-----
.
.
patch 3
-----现在,我想重新安排块,并将它们以新的顺序(wrt,补丁号)写入另一个文件。这个新顺序是在一个列表(如new-order = (3 1 0 2) )中定义的。另外,每个块的第一行的行号(在初始文件中)也是在一个列表(如line-numbers = (0 24 134 210 520) )中定义的。
我的问题是一个很好的方式来编码这个共同的lisp。我编写了以下代码,但在将一些数据写入新文件后,显然该过程陷入了一个无休止的循环,因此我不得不在没有结果的情况下阻止自己:
(with-open-file (out output-stream
:direction :output
:if-exists :new-version
:if-does-not-exist :create)
(with-open-file (in input-stream
:direction :input
:if-does-not-exist nil)
(let ((new-order (list 3 1 0 2)))
(dotimes (n (length new-order))
(loop for line = (read-line in nil 'eof)
for i from 1
do (when (<= (nth (nth n new-order) line-numbers)
i
(nth (1+ (nth n new-order)) line-numbers))
(format out "~a~%" line)))))))这显然不是一个有效的办法,我想知道是什么造成了这个问题,什么是最好的办法?
发布于 2014-01-04 21:18:43
主要问题似乎是每次传递后都需要重置文件位置。无限循环之所以发生,是因为您从未检查过文件结束(并且抑制了信号)。
侧提示:使用dolist代替dotimes和nth结构。
如果您不想进行n次传递(n是修补程序的数目),并且不能将整个内容保存在内存中,则可以将补丁写入临时文件,然后按照所需的顺序将它们连接起来。如果您也没有足够的磁盘空间,它就变成了一个具有不同元素大小的就地排序问题,涉及的问题就更多了。
https://stackoverflow.com/questions/20926741
复制相似问题