Common lisp 在公共lisp中从文件流到关联列表

Common lisp 在公共lisp中从文件流到关联列表,common-lisp,file-read,clos,Common Lisp,File Read,Clos,我有一个以 (defparameter*myfile* ((图例1)(A1 CAN)(A2 4) (南部)(BCZ南部)(功绩为零)(迪尔财政司)(拉多姆全部) (新南威尔士州)(功绩为零)迪尔·布斯(拉多姆全州) ((东北西北西北西北部)(壮举((大名)(()())))) (SEM(lamp(P“CAN”))(PARAM 1.0)) ((键2)(A1克迪伊)(A2 4)…..并继续这样下去 我猜这是一个CLOS,但它存储在一个文件中。我需要能够在assoc列表中获取此数据,以到达A1或A2等。

我有一个以

(defparameter*myfile*
((图例1)(A1 CAN)(A2 4)
(南部)(BCZ南部)(功绩为零)(迪尔财政司)(拉多姆全部)
(新南威尔士州)(功绩为零)迪尔·布斯(拉多姆全州)
((东北西北西北西北部)(壮举((大名)(()()))))
(SEM(lamp(P“CAN”))(PARAM 1.0))
((键2)(A1克迪伊)(A2 4)
…..并继续这样下去

我猜这是一个CLOS,但它存储在一个文件中。我需要能够在assoc列表中获取此数据,以到达A1或A2等。作为键,以获取其值。我现在所做的是逐行读取文件并对其执行字符串操作。但我认为这确实是一个糟糕的做法。这是我现在的代码

(defun open_ded (path)
 (defvar last_id 0)
 (let ((in (open path :if-does-not-exist nil)))
  (when in
    (loop for line = (read-line in nil)
        while line 
            do 
                (if (setq key_id (findkeyid line)) ;search "KEY" and return its id value
                (setq last_id key_id)) ;if it is not nil, set it to last_id

我知道我可以用(defparameter*s*(open“path”))获取整个文件,但是当我想做(assoc'A1(read*s*))或(assoc'键(read*s*))时,我什么也做不到。你对如何实现这一点有什么想法吗?

你可以使用内置函数
load
来读取文件:

(load "/tmp/data.lisp")
这将设置变量
*myfile*
,以便您可以执行以下操作:

* (print *myfile*)

(((KEY 1) (A1 CAN) (A2 4)
  (SUR
   (((BCZ S) (FEATS NIL)) (DIR FS) (LADOM ALL)
    (((NNEW S) (FEATS NIL)) (DIR BS) (LADOM ALL)
     ((NNEW NP) (FEATS ((BIG NOM)))))))
  (SEM (LAM P (P "CAN"))) (PARAM 1.0))
 ((KEY 2) (A1 KEDIYI) (A2 4)))
(((KEY 1) (A1 CAN) (A2 4)
  (SUR
   (((BCZ S) (FEATS NIL)) (DIR FS) (LADOM ALL)
    (((NNEW S) (FEATS NIL)) (DIR BS) (LADOM ALL)
     ((NNEW NP) (FEATS ((BIG NOM)))))))
  (SEM (LAM P (P "CAN"))) (PARAM 1.0))
 ((KEY 2) (A1 KEDIYI) (A2 4)))

* (loop for i from 0
        for entry in *myfile*
        do (format t "Entry #~D: ~S~%" i entry))
Entry #0: ((KEY 1) (A1 CAN) (A2 4)
             (SUR
              (((BCZ S) (FEATS NIL)) (DIR FS) (LADOM ALL)
               (((NNEW S) (FEATS NIL)) (DIR BS) (LADOM ALL)
                ((NNEW NP) (FEATS ((BIG NOM)))))))
             (SEM (LAM P (P "CAN"))) (PARAM 1.0))
Entry #1: ((KEY 2) (A1 KEDIYI) (A2 4))
NIL

* (dolist (entry *myfile*)
     (print (assoc 'key entry)))

(KEY 1)
(KEY 2)
NIL
如果您不信任文件内容,并且您希望读取文件中的源代码但不执行它(加载
),则可以使用
read
。在这种情况下,还可以将
*read eval*
绑定到
nil
,以防止使用
.
在读取时执行代码:

(with-open-file (f "/tmp/data.lisp")
  (let ((*read-eval* nil))
    (loop for form = (read f nil nil)
          while form
          do (print form)))

文件内容看起来像一个条目集合,每个条目都有一个键值对列表。其中没有任何东西可以将其连接到CLOS,尽管您可以使用插槽名称
key
bcz
feats
等定义名为
entry
的结构或类,然后使用
(entry bcz x)等访问器
而不是
(第二(assoc'bcz x))
。这可能有助于提高可读性和效率,但要做到这一点,您需要从基于列表的数据表示中创建对象。

您可以使用内置函数
load
读取文件:

(load "/tmp/data.lisp")
这将设置变量
*myfile*
,以便您可以执行以下操作:

* (print *myfile*)

(((KEY 1) (A1 CAN) (A2 4)
  (SUR
   (((BCZ S) (FEATS NIL)) (DIR FS) (LADOM ALL)
    (((NNEW S) (FEATS NIL)) (DIR BS) (LADOM ALL)
     ((NNEW NP) (FEATS ((BIG NOM)))))))
  (SEM (LAM P (P "CAN"))) (PARAM 1.0))
 ((KEY 2) (A1 KEDIYI) (A2 4)))
(((KEY 1) (A1 CAN) (A2 4)
  (SUR
   (((BCZ S) (FEATS NIL)) (DIR FS) (LADOM ALL)
    (((NNEW S) (FEATS NIL)) (DIR BS) (LADOM ALL)
     ((NNEW NP) (FEATS ((BIG NOM)))))))
  (SEM (LAM P (P "CAN"))) (PARAM 1.0))
 ((KEY 2) (A1 KEDIYI) (A2 4)))

* (loop for i from 0
        for entry in *myfile*
        do (format t "Entry #~D: ~S~%" i entry))
Entry #0: ((KEY 1) (A1 CAN) (A2 4)
             (SUR
              (((BCZ S) (FEATS NIL)) (DIR FS) (LADOM ALL)
               (((NNEW S) (FEATS NIL)) (DIR BS) (LADOM ALL)
                ((NNEW NP) (FEATS ((BIG NOM)))))))
             (SEM (LAM P (P "CAN"))) (PARAM 1.0))
Entry #1: ((KEY 2) (A1 KEDIYI) (A2 4))
NIL

* (dolist (entry *myfile*)
     (print (assoc 'key entry)))

(KEY 1)
(KEY 2)
NIL
如果您不信任文件内容,并且您希望读取文件中的源代码但不执行它(加载
),则可以使用
read
。在这种情况下,还可以将
*read eval*
绑定到
nil
,以防止使用
.
在读取时执行代码:

(with-open-file (f "/tmp/data.lisp")
  (let ((*read-eval* nil))
    (loop for form = (read f nil nil)
          while form
          do (print form)))

文件内容看起来像一个条目集合,每个条目都有一个键值对列表。其中没有任何东西可以将其连接到CLOS,尽管您可以使用插槽名称
key
bcz
feats
等定义名为
entry
的结构或类,然后使用
(entry bcz x)等访问器
而不是
(second(assoc'bcz x))
。这可能有助于提高可读性和效率,但要做到这一点,您需要从基于列表的数据表示中创建对象。

@zut很好地展示了如何在不评估内容的情况下读取文件

我正在使用它,并向您展示如何从第一个表达式获取键值对

;; read-in-first-expression from file
(defparameter *f* (with-open-file (f "~/Dropbox/cl/test-file.lisp")
            (let ((*read-eval* nil))
              (loop for form = (read f nil nil)
                        while form
                collect form))))
*f*
;; first expression (defparameter expression):
(defparameter *f-1st-expr* (first *f*))
*f-1st-expr*

;; ;; I was trying to get to the data part of the first expression trying/using:
;; (first (second (third *f-1st-expr*)))
;; (second (second (third *f-1st-expr*)))

;; let's say these are lists of small lists of length 2

(defun two-element-lists-to-alist (two-list)
  (mapcar (lambda (p) (cons (first p)
                (let ((el (cdr p)))
                  (if (and (atom (car el)) (= (length el) 1))
                  (car el)
                  el))))
      two-list))

(defun convert-to-alists (read-in-defparameter-expression)
  (let ((data (second (third read-in-defparameter-expression))))
    (mapcar #'two-element-lists-to-alist data)))

;; convert to list of alists
(defparameter *alists* (convert-to-alists *f-1st-expr*))

;; ;; one can now access within the list of a lists using assoc and elt
;; ;; the key-value pairs
;; (assoc 'KEY (elt *alists* 0))
;; (assoc 'KEY (elt *alists* 1))
;; (assoc 'A1  (elt *alists* 0))

;; write a function to directly access key-value-pair of nth alist in alists
(defun get-key-from-nth (alists key nth)
  (assoc key (elt alists nth)))

;; testing:
(get-key-from-nth *alists* 'A1 0) ;; (A1 . CAN)
(get-key-from-nth *alists* 'A1 1) ;; (A1 . KEDIYI)
(get-key-from-nth *alists* 'KEY 0) ;; (KEY . 1)
(get-key-from-nth *alists* 'KEY 1) ;; (KEY . 2)
;; works!
~/Dropbox/cl/test file.lisp
的内容是:

    (defparameter *myfile* 
    '(((KEY 1) (A1 CAN) (A2 4)
        (SUR (((BCZ S) (FEATS NIL)) (DIR FS) (LADOM ALL)
        (((NNEW S) (FEATS NIL)) (DIR BS) (LADOM ALL)
        ((NNEW NP) (FEATS ((BIG NOM)))))))
        (SEM (LAM P (P "CAN"))) (PARAM 1.0))
      ((KEY 2) (A1 KEDIYI) (A2 4) 'and-so-on)))

@zut很好地展示了如何在不评估内容的情况下读取文件

我正在使用它,并向您展示如何从第一个表达式获取键值对

;; read-in-first-expression from file
(defparameter *f* (with-open-file (f "~/Dropbox/cl/test-file.lisp")
            (let ((*read-eval* nil))
              (loop for form = (read f nil nil)
                        while form
                collect form))))
*f*
;; first expression (defparameter expression):
(defparameter *f-1st-expr* (first *f*))
*f-1st-expr*

;; ;; I was trying to get to the data part of the first expression trying/using:
;; (first (second (third *f-1st-expr*)))
;; (second (second (third *f-1st-expr*)))

;; let's say these are lists of small lists of length 2

(defun two-element-lists-to-alist (two-list)
  (mapcar (lambda (p) (cons (first p)
                (let ((el (cdr p)))
                  (if (and (atom (car el)) (= (length el) 1))
                  (car el)
                  el))))
      two-list))

(defun convert-to-alists (read-in-defparameter-expression)
  (let ((data (second (third read-in-defparameter-expression))))
    (mapcar #'two-element-lists-to-alist data)))

;; convert to list of alists
(defparameter *alists* (convert-to-alists *f-1st-expr*))

;; ;; one can now access within the list of a lists using assoc and elt
;; ;; the key-value pairs
;; (assoc 'KEY (elt *alists* 0))
;; (assoc 'KEY (elt *alists* 1))
;; (assoc 'A1  (elt *alists* 0))

;; write a function to directly access key-value-pair of nth alist in alists
(defun get-key-from-nth (alists key nth)
  (assoc key (elt alists nth)))

;; testing:
(get-key-from-nth *alists* 'A1 0) ;; (A1 . CAN)
(get-key-from-nth *alists* 'A1 1) ;; (A1 . KEDIYI)
(get-key-from-nth *alists* 'KEY 0) ;; (KEY . 1)
(get-key-from-nth *alists* 'KEY 1) ;; (KEY . 2)
;; works!
~/Dropbox/cl/test file.lisp
的内容是:

    (defparameter *myfile* 
    '(((KEY 1) (A1 CAN) (A2 4)
        (SUR (((BCZ S) (FEATS NIL)) (DIR FS) (LADOM ALL)
        (((NNEW S) (FEATS NIL)) (DIR BS) (LADOM ALL)
        ((NNEW NP) (FEATS ((BIG NOM)))))))
        (SEM (LAM P (P "CAN"))) (PARAM 1.0))
      ((KEY 2) (A1 KEDIYI) (A2 4) 'and-so-on)))

文件中到底是什么?文件中是
defparameter
表单还是以
开头的表单((键1)
?@Svante是的,它从defparameter部分开始,就像您在一起定义一个defparameter,但它在文件中。文件中到底是什么?文件中是
defparameter
表单还是以
开头的表单(((图例1).
?@Svante是的,它从defparameter部分开始,就像您正在一起定义一个defparameter,但它在文件中。这太好了,谢谢。希望我能同时设置两个答案。欢迎!@Karavana-如果我能帮助您,我很高兴!)非常感谢。希望我能同时给出两个答案。欢迎!@Karavana-如果我能帮助你,我很高兴!)谢谢你的时间,这是我一直在寻找的。一个程序生成这个文件,它总是像这样的结构,所以我可以信任它的内容。我想我会尝试创建一个类,然后对象,使它更可读。谢谢你的时间,这就是我一直在寻找的。一个程序生成这个文件,它总是像这样的我想我会尝试创建一个类,然后创建一个对象,使它更具可读性。