我正致力于实现一个神经网络来处理CSV中的MNIST数据集,而不是使用图像。我使用Common Lisp和Quicklisp,以及cl-csv实用程序进行CSV解析。使用cl-csv,如何从CSV返回单行?使用(cl-csv:read-csv-row #P"file.csv")
会返回第1行。尝试(cl-csv:read-csv-row #P"file.csv" 5)
会产生:*** - CL-CSV:READ-CSV-ROW: keyword arguments in (#P"test3.csv") should occur pairwise
。 cl-csv可以返回单个指定的行,如果是,那么如何将行号写为参数?
答案 0 :(得分:1)
一个名为read-…
的函数通常被认为是从流中读取。这涉及改变流的状态,以便下一次读取交互从前一个左侧关闭开始。一个常见的习语是循环执行此操作。
似乎cl-csv希望read-csv-row
的用户将end-of-file
作为信号处理,所以:
(with-open-file (csv-in-stream csv-pathname)
(handler-case
(loop :for csv-line := (read-csv-row csv-in-stream)
:do (process-somehow csv-line))
(end-of-file () (whatever)))
如果您想获得一个特定的行:
(with-open-file (csv-in-stream csv-pathname)
(handler-case
(loop :repeat (1- n)
:do (read-csv-row csv-in-stream) ; skip skip …
:finally (return (read-csv-row csv-in-stream)))
(end-of-file () (oupsie-file-too-short)))
您经常需要使用提供的便利包装器之一:
(do-csv (row csv-pathname)
(process-somehow row))
或使用iterate
:
(iter
(for row in-csv csv-pathname)
(process-somehow row))
我必须承认,我已经非常喜欢替代库fare-csv
。
答案 1 :(得分:0)
<强>解决方案强>:
(ql:quickload 'cl-csv) ; load the cl-csv package
(defun nth-csv-row (csv-path n &rest read-csv-row-parameters)
"Return nth line of a csv file, parsed."
(with-open-file (stream csv-path)
(loop for x from 1 below n
do (cl-csv:read-csv-row stream))
(apply #'cl-csv:read-csv-row stream read-csv-row-parameters)))
;; your example executed using the new function:
(nth-csv-row #P"file.csv" 5)
致@Svante,他指出了我犯的逻辑错误。
(最初,我使用do (read-line stream)
跳过这些行。但由于new-line
字符可以在csv单元格内,我必须使用cl-csv:read-csv-row
来正确解析单元格包含的情况new-line
s。谢谢@Svante!
错误的(!)旧解决方案(仅限教育用途):
(ql:quickload 'cl-csv) ; load the cl-csv package
;; a more general function returning the nth line of a file
(defun nth-line (file-path n)
(with-open-file (stream file-path)
(loop for x from 1 to (1- n)
do (read-line stream))
(read-line stream)))
;; wrap it with a csv parsing function
(defun nth-csv-line (csv-path n &rest read-csv-row-parameters)
"Return nth line of a csv file, parsed."
(apply #'cl-csv:read-csv-row (nth-line csv-path n) read-csv-row-parameters))
;; your example executed using the new function:
(nth-csv-line #P"file.csv" 5)
(如果csv单元格包含换行符,则无法正确解析!) - (read-line)
不会检查new-line
字符是在单元格内还是在单元格外部。“ p>
无论如何 - 现在接下来,我之前评论过的(仍然有效):
自:
[功能] read-csv-row(stream-or-string&amp; key(分隔符 separator )(quote quote )(escape quote-escape )&amp; aux current state line llen c elen)=&gt; 结果
按数据行读取CSV(由于引用的换行符可能更多 来自流的一行) (https://github.com/AccelerationNet/cl-csv/blob/master/DOCUMENTATION.md#read-csv-row)
由于&rest read-csv-row-parameters
将所有其他参数传递给cl-csv:read-csv-row
函数(与R ...
完全相同),
nth-csv-line
具有cl-csv:read-csv-row
功能的全部功能。因此,
此解决方案不仅可以使用逗号分隔,还可以使用任何其他分隔符分隔的数据
示例:
考虑"~/test.csv"
内容:
abc def klm
1 2 3
A B C
(注意:这是制表符分隔文件而不是逗号分隔文件)
解析第二行:
(nth-csv-row "~/test.csv" 2 :separator #\TAB) ; instead of comma
;; returns - correctly parsed: ;; ("1" "2" "3")
附录(正确安装quicklisp,运行这些代码段......)
如果有人读到这篇文章,那么新手想要尝试并且没有quicklisp
工作(我必须重新弄清楚它 - 所以也许可以节省你的时间):
;; ;; If quicklisp is not installed, do on terminal:
;; $ wget https://beta.quicklisp.org/quicklisp.lisp
;; ;; Then in your lisp interpreter:
;; (quicklisp-quickstart:install)
;; ;; following instructions of quickslisp do
;; (load "~/quicklisp/setup.lisp") ; or: path/to/your/quicklisp/setup.lisp
;; With installed quicklisp, you can from now on install and load
;; any quicklisp-able package by:
(ql:quickload 'cl-csv) ; install cl-csv using quicklisp