将 csv 文件读入列表列表的 Lisp 代码。

Lisp code to read csv file into a list of lists.

我从 Python 中获得了这段代码,用于逐行读取 csv(逗号分隔的文本值)文件作为字符串,然后将每个这样的行字符串拆分为字段并在控制台上打印每个字段:

def readfilefn(filename):
    with open(filename,"r") as f:
        for line in f:
            flds = line.split(',')  
            for fld in flds:
                print fld.strip()

我正在尝试将其转换为 Lisp 代码。我在 How can I read the contents of a file into a list in Lisp? 上找到了以下代码:

(defun get-file (filename)
  (with-open-file (stream filename)
    (loop for line = (read-line stream nil)
          while line
          collect line)))

还有一个来自:https://groups.google.com/forum/#!topic/comp.lang.lisp/r8O6Py8E1zE

(defun read-all-lines (input-stream)
  (do ((line nil)
       (result nil (cons line result)))
      ((eq line :eof) (nreverse result))
   (setq line (read-line input-stream nil :eof))))

(此处必须使用 nreverse 反转行)。

用于将完整行字符串拆分为字段字符串:https://gist.github.com/siguremon/1174988

(defun split-str (string &optional (separator " "))
  (split-str-1 string separator))

(defun split-str-1 (string &optional (separator " ") (r nil))
  (let ((n (position separator string
             :from-end t
             :test #'(lambda (x y)
                   (find y x :test #'string=)))))
    (if n
    (split-str-1 (subseq string 0 n) separator (cons (subseq string (1+ n)) r))
      (cons string r))))

还有许多其他例程随处可用,例如http://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/need-a-lisp-routine-to-string-split/td-p/2618387

我想知道这些方法是否安全,或者哪种方法最好。我在 Linux 上使用 clisp (Common Lisp)。感谢您的 comments/answers。

抱歉来晚了,正如 jkilky 在评论中所建议的,我将使用通用的 lisp 库 cl-csv,它可以通过 quicklisp 获得。

CL-USER> (ql:quickload :cl-csv)
To load "cl-csv":
  Load 1 ASDF system:
    cl-csv
; Loading "cl-csv"
...
(:CL-CSV)

cl-csv 将您的文件拆分为列表列表让我们使用来自 here 的 csv 文件 train.csv 是一个普通的 csv 文件:

PassengerId,Survived,Pclass,Name,Sex,Age,SibSp,Parch,Ticket,Fare,Cabin,Embarked
1,0,3,"Braund, Mr. Owen Harris",male,22,1,0,A/5 21171,7.25,,S
2,1,1,"Cumings, Mrs. John Bradley (Florence Briggs Thayer)",female,38,1,0,PC 17599,71.2833,C85,C
3,1,3,"Heikkinen, Miss. Laina",female,26,0,0,STON/O2. 3101282,7.925,,S
4,1,1,"Futrelle, Mrs. Jacques Heath (Lily May Peel)",female,35,1,0,113803,53.1,C123,S
5,0,3,"Allen, Mr. William Henry",male,35,0,0,373450,8.05,,S
6,0,3,"Moran, Mr. James",male,,0,0,330877,8.4583,,Q
7,0,1,"McCarthy, Mr. Timothy J",male,54,0,0,17463,51.8625,E46,S
8,0,3,"Palsson, Master. Gosta Leonard",male,2,3,1,349909,21.075,,S
9,1,3,"Johnson, Mrs. Oscar W (Elisabeth Vilhelmina Berg)",female,27,0,2,347742,11.1333,,S
10,1,2,"Nasser, Mrs. Nicholas (Adele Achem)",female,14,1,0,237736,30.0708,,C
11,1,3,"Sandstrom, Miss. Marguerite Rut",female,4,1,1,PP 9549,16.7,G6,S
12,1,1,"Bonnell, Miss. Elizabeth",female,58,0,0,113783,26.55,C103,S
13,0,3,"Saundercock, Mr. William Henry",male,20,0,0,A/5. 2151,8.05,,S
...
...

Cl-csv 将其加载到列表列表中,每一行都是一个列表:

CL-USER> (cl-csv:read-csv #P"./train.csv")
(("PassengerId" "Survived" "Pclass" "Name" "Sex" "Age" "SibSp" "Parch" "Ticket"
  "Fare" "Cabin" "Embarked")
 ("1" "0" "3" "Braund, Mr. Owen Harris" "male" "22" "1" "0" "A/5 21171" "7.25"
  "" "S")
 ("2" "1" "1" "Cumings, Mrs. John Bradley (Florence Briggs Thayer)" "female"
  "38" "1" "0" "PC 17599" "71.2833" "C85" "C")
 ("3" "1" "3" "Heikkinen, Miss. Laina" "female" "26" "0" "0" "STON/O2. 3101282"
  "7.925" "" "S")
 ("4" "1" "1" "Futrelle, Mrs. Jacques Heath (Lily May Peel)" "female" "35" "1"
  "0" "113803" "53.1" "C123" "S")
 ("5" "0" "3" "Allen, Mr. William Henry" "male" "35" "0" "0" "373450" "8.05" ""
  "S")
 ("6" "0" "3" "Moran, Mr. James" "male" "" "0" "0" "330877" "8.4583" "" "Q")
 ("7" "0" "1" "McCarthy, Mr. Timothy J" "male" "54" "0" "0" "17463" "51.8625"
  "E46" "S")
 ("8" "0" "3" "Palsson, Master. Gosta Leonard" "male" "2" "3" "1" "349909"
  "21.075" "" "S")

然后使用 format 函数将其打印出来,这是打印列表的一个小技巧,每个列表都有一个分隔符,我使用 nil 而不是 t 来获取字符串,但你可以用 t 打印它,所以这是在 lisp 中得到这个的单行代码,我为第一级列表(然后是行)使用了新的行分隔符,然后为行的项目使用了“,”:

CL-USER> (format nil "~{~{~a,  ~}~% ~}" (cl-csv:read-csv #P"train.csv"))

"PassengerId,  Survived,  Pclass,  Name,  Sex,  Age,  SibSp,  Parch,  Ticket,  Fare,  Cabin,  Embarked,  
 1,  0,  3,  Braund, Mr. Owen Harris,  male,  22,  1,  0,  A/5 21171,  7.25,  ,  S,  
 2,  1,  1,  Cumings, Mrs. John Bradley (Florence Briggs Thayer),  female,  38,  1,  0,  PC 17599,  71.2833,  C85,  C,  
 3,  1,  3,  Heikkinen, Miss. Laina,  female,  26,  0,  0,  STON/O2. 3101282,  7.925,  ,  S,  
 4,  1,  1,  Futrelle, Mrs. Jacques Heath (Lily May Peel),  female,  35,  1,  0,  113803,  53.1,  C123,  S,  
 5,  0,  3,  Allen, Mr. William Henry,  male,  35,  0,  0,  373450,  8.05,  ,  S,  
 6,  0,  3,  Moran, Mr. James,  male,  ,  0,  0,  330877,  8.4583,  ,  Q,  
 7,  0,  1,  McCarthy, Mr. Timothy J,  male,  54,  0,  0,  17463,  51.8625,  E46,  S,  
 8,  0,  3,  Palsson, Master. Gosta Leonard,  male,  2,  3,  1,  349909,  21.075,  ,  S,  
 9,  1,  3,  Johnson, Mrs. Oscar W (Elisabeth Vilhelmina Berg),  female,  27,  0,  2,  347742,  11.1333,  ,  S,  
 10,  1,  2,  Nasser, Mrs. Nicholas (Adele Achem),  female,  14,  1,  0,  237736,  30.0708,  ,  C,  
 11,  1,  3,  Sandstrom, Miss. Marguerite Rut,  female,  4,  1,  1,  PP 9549,  16.7,  G6,  S,  
 12,  1,  1,  Bonnell, Miss. Elizabeth,  female,  58,  0,  0,  113783,  26.55,  C103,  S,  
 13,  0,  3,  Saundercock, Mr. William Henry,  male,  20,  0,  0,  A/5. 2151,  8.05,  ,  S,  
 14,  0,  3,  Andersson, Mr. Anders Johan,  male,  39,  1,  5,  347082,  31.275,  ,  S,  
 15,  0,  3,  Vestrom, Miss. Hulda Amanda Adolfina,  female,  14,  0,  0,  350406,  7.8542,  ,  S,  
 16,  1,  2,  Hewlett, Mrs. (Mary D Kingcome) ,  female,  55,  0,  0,  248706,  16,  ,  S,  
 17,  0,  3,  Rice, Master. Eugene,  male,  2,  4,  1,  382652,  29.125,  ,  Q,  
 18,  1,  2,  Williams, Mr. Charles Eugene,  male,  ,  0,  0,  244373,  13,  ,  S,  
 19,  0,  3,  Vander Planke, Mrs. Julius (Emelia Maria Vandemoortele),  female,  31,  1,  0,  345763,  18,  ,  S, 

希望对您有所帮助