【发布时间】:2016-08-17 09:03:12
【问题描述】:
对于我的一个项目,我正在尝试使用 Common Lisp,特别是 SBCL(在此过程中,学习它。这是动机之一。)
我需要阅读一个包含问题和答案的文件,基本上就像一个主要包含多项选择问题答案的标准化测试。
我有一些用“|”之类的部分标记标记的示例问题用于开始和“//s”用于和部分。试卷将具有这样的层次结构:部分 -> 多个子部分 -> 每个子部分有多个问题 -> 每个问题将有多个答案,其中一个是正确的。
这个层次结构最终需要转换成一个json文件,推送到一个android app上供下游消费。
STEP-1:阅读源测试文件后,我的列表将如下所示:
(("Test" . "t")
("0.1" . "v")
("today" . "d")
("General Knowledge" . "p")
("Science" . "s")
("what is the speed of light in miles per second?" . "q")
("Choose the best answer from the following" . "i")
("MCQ question" . "n")
("186000" . "c")
("286262" . "w")
("200000" . "w"))
[PS.1]请参阅帖子末尾的图例,了解 h、p、t、v 等 cdar 值的解释, p>
[PS.2]本文末尾附上的源文件示例
consed 对中的每辆汽车代表内容,cdr 代表部分 - 这将对应于一个部分、子部分或一个问题等,
STEP-2:最后我需要把它转换成下面的格式——一个alist——
((:QANDA . "Test") (:VERSION . "0.1") (:DATE . "today")
(:SECTION
((:TITLE . "General Knowledge")
(:SUBSECTION
((:SSTITLE . "Science")
(:QUESTION
((:QUESTION . "what is the speed of light in miles per second?")
(:DIRECTIONS . "Choose the best answer from the following")
(:TYPE . "MCQ question")
(:CHOICES ((:CHOICE . "186000") (:CORRECT . "Y"))
((:CHOICE . "286000") (:CORRECT . "N"))
((:CHOICE . "200000") (:CORRECT . "N"))))))))))
由 cl-json 使用。
STEP-3: cl-json 会从中生成一个合适的 json。
json 将如下所示:
{
"qanda": "Test",
"version": "0.1",
"date": "today",
"section": [
{
"title": "General Knowledge",
"subsection": [
{
"sstitle": "Science",
"question": [
{
"question": "what is the speed of light in miles per second?",
"Directions": "Choose the best answer from the following",
"type": "MCQ question",
"choices": [
{
"choice": "186000",
"Correct": "Y"
},
{
"choice": "286000",
"Correct": "N"
},
{
"choice": "200000",
"Correct": "N"
}
]
}
]
}
]
}
]
}
我已成功读取源文件,生成 consed 对列表。我正在努力的地方是创建这个嵌套列表,如上所示,以将其提供给 cl-json。
经过一番挣扎后,我意识到这或多或少像一个 n 叉树问题。
这是我的问题:
a) 构建试卷源文件的这种 n 叉树表示的正确方法是什么?
b) 或者是否有更好或更简单的数据结构来表示这一点?
这是我尝试过的,其中 qtree 最初是 '() 而 kvlist 是上面显示的 consed 对列表。这是一个不完整的代码,因为我尝试了 push.、consing 和 nconc(结果不可靠)。
步骤 1 和步骤 3 都可以。第2步是我需要帮助的地方。问题是如何通过迭代kvlist来连续添加子节点,并在有多个父节点时找到合适的父节点来添加子节点(例如,向第二个子节点添加问题-部分):
(defun build-qtree (qtree kvlist)
(cond
((eq '() kvlist) qtree)
((equal "h" (cdar kvlist))
(push (car kvlist) qtree)
(build-qtree qtree (cdr kvlist)))
((equal "p" (cdar kvlist))
(nconc (last qtree) '((:SECTION))))
(t
(qtree))))
[PS.1] 图例:这将在条件分支中使用,也可以是defstruct或字典类型的列表等,
t - 标题,v - 版本,d - 日期,p - 部分,s - 子部分,q - 问题,i - 说明,n - 问题类型,c - 正确答案,w - 错误答案
[PS.2]源文件:
|Test//t
|0.1//v
|today//d
|General Knowledge//p
|Science//s
|what is the speed of light in miles per second?//q
|Choose the best answer from the following//i
|MCQ question//n
|186000//c
|286000//w
|200000//w
【问题讨论】:
-
所有这三个例子似乎代表了完全不同的数据。您可以添加输入文件的实际示例以及所需的每种不同格式的数据吗?
-
@jkiiski 这些都是我尝试过很多事情的零散示例。对不起。删除它们并在整个过程中添加了一个示例。
标签: parsing lisp common-lisp