【问题标题】:Clisp reading list from file and flatten it, but not working, doesnt recognize lst as a list从文件中剪辑阅读列表并将其展平,但不工作,不将 lst 识别为列表
【发布时间】:2021-02-04 01:39:08
【问题描述】:
(defun read-file-list (infile)
  (with-open-file (instream infile :direction :input :if-does-not-exist nil)
   (when instream 
     (let ((list (make-list (file-length instream))))
       (read-sequence list instream)
       list))))


(setq lst (read-file-list "/home/Desktop/nested_list.txt"))

(flatten-list lst )

(print lst)

;(1 2 3 (4 5 (12 11 9 6) 4 8 (77 53(47)) (12 15 18)) 
; file has got this line

【问题讨论】:

  • 请注意,file-length 可能不会告诉您读取文件时您想知道什么,如果您将其作为字符读取,因为至少在 Unixoid 系统上,了解文件的唯一方法是这样一个文件的长度以字符为单位,而不是以字节为单位,是读取整个文件。
  • 您需要清楚地描述实际问题的原因。例如 FLATTEN-LIST 似乎与您的问题无关。
  • @RainerJoswig 主要思想是展平,展平有错误但我的文件不是列表类型,我需要将其转换为列表类型

标签: lisp common-lisp clisp


【解决方案1】:

READ-SEQUENCE 从文件中读取字符。当您计算file-length 并调用read-sequence 时,您所做的就是读取平面列表中的所有字符。即,您的示例中的lst 是这个列表:

(#\( #\1 #\  #\2 #\  #\3 #\  #\( #\4 #\  #\5 #\  #\( #\1 #\2 #\  #\1 #\1 #\
 #\9 #\  #\6 #\) #\  #\4 #\  #\8 #\  #\( #\7 #\7 #\  #\5 #\3 #\( #\4 #\7 #\)
 #\) #\  #\( #\1 #\2 #\  #\1 #\5 #\  #\1 #\8 #\) #\) #\Newline)

您可以看到此列表中的所有元素都是字符,它们用#\... 语法表示。例如,第一项描述如下(使用 SBCL 测试,实际输出可能在您的实现中有所不同):

* (describe (first lst))
#\(
[standard-char]

Char-code: 40
Char-name: LEFT_PARENTHESIS
; No value

(with-open-file (stream "/tmp/file-list.txt") (读 (make-concatenated-stream (make-string-input-stream "(") 溪流 (make-string-input-stream ")")))) 您要做的是在该文件上调用READ

* (with-open-file (in "/tmp/file-list.txt")
    (read in))
; Evaluation aborted on #<END-OF-FILE {1013420B23}>.

而且您的输入文件似乎也缺少右括号。修复后,您有:

* (with-open-file (in "/tmp/file-list.txt")
    (read in))
(1 2 3 (4 5 (12 11 9 6) 4 8 (77 53 (47)) (12 15 18)))

这里读取的值是一个数字列表和嵌套列表。

* (describe (first *))
1
[fixnum]
; No value

---- 编辑

您的flatten-list 函数似乎有效,我的意思是您的输入列表在另一个文件中,您需要通过调用read 使用标准Lisp 阅读器提取数据:

* (with-open-file (in "/tmp/file-list.txt")
    (flatten-list (read in)))

(1 2 3 4 5 12 11 9 6 4 8 77 53 47 12 15 18)

--- 编辑 2

如果您的文件包含列表元素,如下所示:

1 2 3 (4 5 (12 11 9 6) 4 8 (77 53(47)) (12 15 18))

然后你可以写一个循环,如下:

(loop 
  for form = (read in nil in)
  until (eq form in)
  collect form)

或者,您可以使用串联流:

USER> (with-input-from-string (open "(")
        (with-input-from-string (close ")")
          (with-open-file (file "/tmp/file-list.txt")
            (read (make-concatenated-stream open file close)))))
(1 2 3 (4 5 (12 11 9 6) 4 8 (77 53 (47)) (12 15 18)))

或等效:

(with-open-file (stream "/tmp/file-list.txt")
  (read (make-concatenated-stream (make-string-input-stream "(")
                                  stream
                                  (make-string-input-stream ")"))))

【讨论】:

  • 你的建议是什么,我不明白,flatten func 适用于手动输入,但 lst 不适用于
  • 是的,你的lst是一个字符列表,“#\0”是一个字符,你在"0123"之类的字符串中找到的那种值,这与数字0不同. 你正在从输入文件中读取字符,所以你有一个很大的字符列表,包括像 "#(" 左括号这样的字符;你需要做的是将文件解析为 lisp 数据,这样一个字符串 @987654343 @ 实际上读作列表(0 1 (2)),而不是字符序列(#\0 #\1 #\( #\2 #\) #\))(注意这是一个平面列表)。
  • 好的,这行得通,谢谢,但如果我的文件不以'('括号开头,它会给出错误,1不是列表
  • @Srknsmsk 如果您的文件不包含 Lisp 列表的语法,而是包含单个项目,那么您必须循环读取它们并将它们累积到一个列表中。
  • 我是用字符串做的,但字符串包含其他字符,我为此使用了 getfromstring 函数
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-02-28
  • 2018-02-01
  • 2016-01-26
  • 1970-01-01
  • 2022-11-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多