对于我的一个项目,我正在尝试使用Common Lisp,特别是SBCL(在此过程中,学习它。这是其中一个动机。)
我需要阅读一个带有问题和答案的文件,基本上就像一个主要是多项选择题答案的标准化考试。
我有一些标有一些标记的示例问题,如" |"开始和" // s"为了和一节。问题文件将具有这样的层次结构:部分 - >多个子部分 - >每个子部分都有多个问题 - >每个问题都有多个答案,其中一个是正确的。
这个层次结构最终需要转换为json文件并推送到Android应用程序以供下游使用。
STEP-1:从源测试论文中读取后,这就是我的列表的样子:
initializeDownloadUI();
Intent launchIntent = ExpansionDownloader.this.getIntent();
Intent intentToLaunchThisActivityFromNotification = new Intent(
ExpansionDownloader.this,
ExpansionDownloader.this.getClass());
intentToLaunchThisActivityFromNotification
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TOP);
intentToLaunchThisActivityFromNotification
.setAction(launchIntent.getAction());
if (launchIntent.getCategories() != null) {
for (String category : launchIntent.getCategories()) {
intentToLaunchThisActivityFromNotification
.addCategory(category);
}
}
// Build PendingIntent used to open this activity from
// Notification
PendingIntent pendingIntent = PendingIntent.getActivity(
ExpansionDownloader.this, 0,
intentToLaunchThisActivityFromNotification,
PendingIntent.FLAG_UPDATE_CURRENT);
// Request to start the download
int startResult = DownloaderClientMarshaller
.startDownloadServiceIfRequired(this, pendingIntent,
ExpansionService.class);
if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) {
// The DownloaderService has started downloading the files,
// show progress
initializeDownloadUI();
return;
} // otherwise, download not needed so we fall through to
// starting the movie
} catch (NameNotFoundException e) {
Log.e(LOG_TAG, "Cannot find own package! MAYDAY!");
e.printStackTrace();
}
[PS.1] 请参阅帖子末尾的图例,了解对cdar值的解释,如h,p,t,v等,
[PS.2] 在此帖末尾附上的源文件示例
表示内容的consed对中的每辆车和代表该部分的cdr - 将对应于部分,子部分或问题等。
第2步:最后我需要将其转换为以下格式 - alist -
(("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"))
被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 pair列表。我正在努力的是创建这个嵌套列表,如上所示,以将其提供给cl-json。
经过一番努力,我意识到这或多或少就像一个n-ary树问题。
以下是我的问题:
a)构建Test纸源文件的这种n-ary树表示的正确方法是什么?
b)或者是否有更好或更简单的数据结构来代表这个?
这是我尝试过的,其中qtree最初是'(),kvlist是上面显示的consed pair列表。这是一个不完整的代码,因为我尝试了push。,consing和nconc(结果不可靠)。
步骤1和步骤3都没问题。第二步是我需要帮助的地方。问题是如何通过迭代kvlist连续添加子节点,并找到正确的父节点,当有多个父节点时添加子节点(例如,向第二个子节点添加一个问题) -section):
{
"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"
}
]
}
]
}
]
}
]
}
[PS.1]图例:这将在条件分支中使用,或者可能是defstruct或字典类型的列表等。
t - title,v - version,d - date,p - section,s - sub section,q - question,i - instructions,n - type of question,c - correct reply,w - wrong answers
[PS.2]源文件:
(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))))
答案 0 :(得分:3)
您遇到一个复杂示例的简单问题。它可能只是一个简单的解析问题:你需要的是语法和解析器。
示例语法。终端项目为大写。 *
表示一个或多个。
s = q
q = Q i*
i = I w*
w = W
简单解析器:
(defun example (sentence)
(labels ((next-item ()
(pop sentence))
(empty? ()
(null sentence))
(peek-item ()
(unless (empty?)
(first sentence)))
(expect-item (sym)
(let ((item (next-item)))
(if (eq item sym)
sym
(error "Parser error: next ~a, expected ~a" item sym))))
(star (sym fn)
(cons (funcall fn)
(loop while (eq (peek-item) sym)
collect (funcall fn)))))
(labels ((s ()
(q))
(q ()
(list (expect-item 'q) (star 'i #'i)))
(i ()
(list (expect-item 'i) (star 'w #'w)))
(w ()
(expect-item 'w)))
(s))))
示例:
CL-USER 10 > (example '(q i w w w i w w))
(Q
((I (W
W
W))
(I (W
W))))