Common Lisp中的快速CSV读取

以这样的方式读取CL中的csv文件的最快方法是什么:

1)第一行中的所有字段都进入一个名为column-names的数组

2)以下所有行中的每一行的第一个字段进入另一个字段

   数组称为行名

3)所有其他字段进入另一个名为values的数组

我的文件有以下形式,只有更多的列和行:

"";"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)))))

注意:我不会在实际代码中使用set-syntax-from-char,我只是为了这个例子而使用它.

最佳答案 我怀疑I / O是这里最慢的部分.如果使用
READ-SEQUENCE而不是反复调用
READ-LINE,则可能会获得更快的I / O.所以你的代码看起来像这样:

(with-open-file (s "my-file.csv")
  (let* ((len (file-length s))
         (data (make-array len)))
    (read-sequence data s)
     data))

然后按换行分割数据并添加逻辑.

无论是否有帮助,您都可以对自己的代码进行分析,例如:用:sb-sprof,看看大部分时间花在哪里.

点赞