读取CL中csv文件的最快方法是: 1)第一行中的所有字段都进入一个名为列名称的数组中 2)第一个字段以下所有行中的每一行进入另一个 数组,称为行名称 3)所有其他字段进入另一个数组,称为值 ?Common Lisp中的快速CSV读取
我的文件中有如下形式,只是多了很多列和行:
"";"ES1 Index";"VG1 Index";"TY1 Comdty";"RX1 Comdty";"GC1 Comdty"
"1999-01-04";1391.12;3034.53;66.515625;86.2;441.39
"1999-01-05";1404.86;3072.41;66.3125;86.17;440.63
"1999-01-06";1435.12;3156.59;66.4375;86.32;441.7
"1999-01-07";1432.32;3106.08;66.25;86.22;447.67
而且我想结果是:
#("1999-01-04" "1999-01-05" "1999-01-06" "1999-01-07")
#("" "ES1 Index" "VG1 Index" "TY1 Comdty" "RX1 Comdty" "GC1 Comdty")
#(1391.12 3034.53 66.515625 86.2 441.39 1404.86 3072.41 66.3125 86.17 440.63
1435.12 3156.59 66.4375 86.32 441.7 1432.32 3106.08 66.25 86.22 447.67)
你知道一些CL库那这样做了吗? 是否有任何关于I/O性能的普遍问题,或许是编译器特有的,我应该知道?
这里是这样,我现在这样做:
(with-open-file (stream "my-file.csv" :direction :input)
(let* ((header (read-line stream nil))
(columns-list (mapcar #'read-from-string
(cl-ppcre:split ";" header)))
(number-of-columns (length columns-list))
(column-names (make-array number-of-columns
:initial-contents columns-list))
(rownames (make-array 1 :adjustable t :fill-pointer 0))
(values (make-array 1 :adjustable t :fill-pointer 0)))
(set-syntax-from-char #\; #\)
(loop
:for reader = (read stream nil stream)
:until (eq reader stream)
:do (progn (vector-push-extend reader row-names)
(loop
:for count :from 2 :upto number-of-columns
:do (vector-push-extend (read stream nil)
values)))
:finally (return (values row-names
column-names
values)))))
注:我不会用设置语法从炭在实际的代码,我使用它只是为了这个例子的目的。
其他答案给你最快的便携方式。最快的不可移植的方式是尽量减少复制(最慢的部分)。复制是在分割字符串时发生的(例如,基于引号或在读线中的新行分割)。如果您的实现可以被确信实现并支持某种C FFI,它允许您在某个只存储指针和长度的cl对象中引用c样式数组,那么您可以将csv文件进行mmap映射并解析它ram,通过指向内存中的文件来建立你的字符串。这不需要复制,但不会允许转义引号。 –