I have to read in a file with the following format: the first line
has a single integer, the following lines consist of vectors of
floating-point values with dimensionality indicated by the integer,
like this:
5
13.575570 12.656892 -1.424328 -2.302774 404.921600
13.844373 12.610620 -1.435429 -1.964423 404.978180
13.996934 12.669785 -1.384147 -1.830788 405.187378
Here's the defun I wrote:
(defun read-vectors (input-file)
(let (sample-vector-list)
(with-open-file (input-file (merge-pathnames input-file))
(do* ((sample-vector-length (read input-file))
(sample-vector nil)
(line (read-line input-file) (read-line input-file nil 'eof)))
((eq line 'eof) t)
(when (not (string-equal line ""))
(setq sample-vector (make-array sample-vector-length))
(with-open-stream (s (make-string-input-stream line))
(dotimes (i sample-vector-length)
(setf (aref sample-vector i)
(read s))))
(push sample-vector sample-vector-list))))
(values sample-vector-list)))
It works, but somehow I have the feeling it's overly complicated.
I'd welcome any suggestions on how to make it better (i.e. simpler,
faster, better style, more memory-effective, whatever) - I'm
re-learning Lisp after a long hiatus and would of course like to
learn how to do things right.
--
Do you agree that I can buy five pizzas and get the sixth free?
In article <··············@ola.hex.fi>, Ola Rinta-Koski
<···············@iki.fi.no.spam.today> wrote:
> It works, but somehow I have the feeling it's overly complicated.
> I'd welcome any suggestions on how to make it better (i.e. simpler,
> faster, better style, more memory-effective, whatever) - I'm
> re-learning Lisp after a long hiatus and would of course like to
> learn how to do things right.
Another quick hack...
(defun read-vectors (input-file)
(with-open-file (stream (merge-pathnames input-file))
(let ((sample-vector-length (read stream nil nil)))
(when sample-vector-length
(loop for vector = (read-a-line sample-vector-length stream)
while vector
collect vector)))))
(defun read-a-line (dimension stream)
(loop with vector = (make-array dimension)
for i from 0 below dimension
for number = (read stream nil nil)
unless number
do (return-from read-a-line nil)
do (setf (aref vector i) number)
finally (return vector)))
--
http://www.lavielle.com/~joswig
Perhaps you might want to consider having the function read the numbers
for the vectors in from the file itself rather than reading a line in as
a string and then running it through the read process again.
Perhaps something like:
(defun read-vectors (input-file)
(with-open-file (input-file (merge-pathnames input-file))
(let ((sample-vector-list nil)
(sample-vector-length (read input-file))
datum)
(block read-data
(loop ;; forever
(let ((sample-vector (make-array sample-vector-length)))
(dotimes (i sample-vector-length)
(setq datum (read input-file nil :eof))
(when (eq datum :eof) ;; End Processing.
(return-from read-data))
(setf (aref sample-vector i) datum))
(push sample-vector sample-vector-list))))
(nreverse sample-vector-list))))
--
Thomas A. Russ, USC/Information Sciences Institute ···@isi.edu