Hello,
I have an ASCII file that gets written by some other (non-lispy) process
and contains (a known number of) integers, one per line, e.g. like this:
8
7
7
5
Now I want to read these numbers into a list, so that instead of
hard-coding the numbers like
(let ((my-list (list 8 7 7 5)))
(do-something-with-the-list))
I can have something like
(let ((my-list (unknown-code-to-read-from-an-include-file)))
(do-something-with-the-list))
Unfortunately, I have no elegant solution how "unknown-code-to-read-from-an-include-file" should look (in Common Lisp
or Emacs Lisp). The best I could come up with is
(require 'f) ; An Emacs library for file handling
(let ((my-list (mapcar #'string-to-number
(split-string (f-read "ascii-file.el")))))
(do-something-with-the-list))
"f-read" returns a string, so I need to convert into a list of strings
and then into a list of numbers. Works, but looks clumsy.
A simple "load-file" will not do, since it just returns T (for successful reading), not the three integer numbers read, so "my-list" is no list,
but the truthiness value.
Any ideas?
Axel Reichert <mail @axel-reichert.de> writes:<snip>
I have an ASCII file that gets written by some other (non-lispy) process
and contains (a known number of) integers, one per line, e.g. like this:
8
7
7
5
Now I want to read these numbers into a list, so that instead of
hard-coding the numbers like
(let ((my-list (list 8 7 7 5)))
(do-something-with-the-list))
(require 'f) ; An Emacs library for file handling
(let ((my-list (mapcar #'string-to-number
(split-string (f-read "ascii-file.el")))))
(do-something-with-the-list))
"f-read" returns a string, so I need to convert into a list of strings
and then into a list of numbers. Works, but looks clumsy.
A simple "load-file" will not do, since it just returns T (for successful
reading), not the three integer numbers read, so "my-list" is no list,
but the truthiness value.
Any ideas?
The task seems straightforward and it looks you solved it. It will look
a lot better if you abstract your strategy away in a procedure. So your
code will look like
(do-something-with (file->list-of-numbers "ascii.file.txt")).
I don't much ELISP, but we might not be too far off with
(defun file->list-of-numbers (fname)
(mapcar #'string-to-number
(split-string (f-read fname))))
The task seems straightforward and it looks you solved it. It will look
a lot better if you abstract your strategy away in a procedure. So your
code will look like
(do-something-with (file->list-of-numbers "ascii.file.txt")).
(car (read-from-string (concat "(" (f-read "file.txt") ")")))
A simple "load-file" will not do, since it just returns T (for successful
reading), not the three integer numbers read, so "my-list" is no list,
but the truthiness value.
Actually LOAD returns T for successful *evaluation* .In your example , it read and evaluated each of the forms 8 , 7 , 7 , 5 .Each of those evaluates to itself [i.e. the respective number] so obviously the evaluation was successful.
For people who don't like extended loop,
(defun read-numbers-from-file/2 (file-path n)
(with-open-file (f file-path :direction :input)
(let ((res nil))
(dotimes (i n)
(push (parse-integer (read-line f nil)) res))
(nreverse res))))
For people who don't like extended loop, I think this a better implementation:
(defun read-numbers-from-file/2 (file-path n)
(with-open-file (f file-path :direction :input)
(let ((res nil))
(dotimes (i n)
(push (parse-integer (read-line f nil)) res))
(nreverse res))))
Raymond Wiker wrote:
For people who don't like extended loop, I think this a better implementation:
(defun read-numbers-from-file/2 (file-path n)
(with-open-file (f file-path :direction :input)
(let ((res nil))
(dotimes (i n)
(push (parse-integer (read-line f nil)) res))
(nreverse res))))
Gauche Scheme
(with-input-from-file "output.dat"
(lambda res
(until (read) eof-object? => x
(push! res x))
(reverse res)))
===>
(4 3 2 1 3 4 2 1 4 2 3 1 2 4 3 1 3 2 4 1 2 3 4 1 4 3 1 2
3 4 1 2 4 1 3 2 1 4 3 2 3 1 4 2 1 3 4 2 4 2 1 3 2 4 1 3
4 1 2 3 1 4 2 3 2 1 4 3 1 2 4 3 3 2 1 4 2 3 1 4 3 1 2 4
1 3 2 4 2 1 3 4 1 2 3 4)
B. Pym wrote:
Raymond Wiker wrote:
For people who don't like extended loop, I think this a better implementation:
(defun read-numbers-from-file/2 (file-path n)
(with-open-file (f file-path :direction :input)
(let ((res nil))
(dotimes (i n)
(push (parse-integer (read-line f nil)) res))
(nreverse res))))
Gauche Scheme
(with-input-from-file "output.dat"
(lambda res
(until (read) eof-object? => x
(push! res x))
(reverse res)))
===>
(4 3 2 1 3 4 2 1 4 2 3 1 2 4 3 1 3 2 4 1 2 3 4 1 4 3 1 2
3 4 1 2 4 1 3 2 1 4 3 2 3 1 4 2 1 3 4 2 4 2 1 3 2 4 1 3
4 1 2 3 1 4 2 3 2 1 4 3 1 2 4 3 3 2 1 4 2 3 1 4 3 1 2 4
1 3 2 4 2 1 3 4 1 2 3 4)
(define (collect-till pred gen key)
(do ((x (gen) (gen))
(res '() (cons x res)))
((pred x) (reverse res))))
(with-input-from-file "output.dat"
(lambda _
(collect-till eof-object? read +)))
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 388 |
Nodes: | 16 (2 / 14) |
Uptime: | 09:49:14 |
Calls: | 8,221 |
Files: | 13,122 |
Messages: | 5,872,631 |