List 如何将列表与数据库序言进行比较
我有一个事实数据库,里面有这样的条目List 如何将列表与数据库序言进行比较,list,prolog,compare,List,Prolog,Compare,我有一个事实数据库,里面有这样的条目 symptom(shingles,headache). symptom(shingles,fever). symptom(shingles,malaise). symptom(shingles,headache). symptom(shingles,itching). symptom(shingles,hyperesthesia). symptom(shingles,paresthesia). test
symptom(shingles,headache).
symptom(shingles,fever).
symptom(shingles,malaise).
symptom(shingles,headache).
symptom(shingles,itching).
symptom(shingles,hyperesthesia).
symptom(shingles,paresthesia).
test(shingles,blood).
test(shingles,pcr).
locale(shingles,all).
treatment(shingles,calamine).
treatment(shingles,aciclovir).
treatment(shingles,valaciclovir).
treatment(shingles,famciclovir).
treatment(shingles,corticosteroids).
然后我有一个谓词,它从用户那里获取症状列表
getSymptoms(Symptoms) :-
write('Please enter symptoms now, enter "Done" when finished: ' ),
read_string(user, "\n", "\r", _, Response),
(
Response == "Done"
->
Symptoms = []
;
getSymptoms(Symptoms0),
Symptoms = [Response|Symptoms0]
).
我的问题是如何将用户症状列表与第二个atom的症状事实进行比较,然后将疾病添加到另一个列表中?
例如,用户输入发烧。由于带状疱疹的症状事实中有发热,它会将带状疱疹添加到列表中。这会起作用,但允许输入重复的症状。我现在发布它,以便您可以看到转换的第一部分,并在我开始工作时发布没有副本的部分
getSymptoms(Symptoms) :-
write('Please enter symptoms now, enter "Done" when finished: ' ),
read_string(user, "\n", "\r", _, Response),
(
Response == "Done"
->
Symptoms = []
;
atom_string(Symptom,Response),
valid_symptom(Symptom,Symptoms)
).
valid_symptom(Symptom,Symptoms) :-
(
symptom(_,Symptom)
->
% Symptom was valid
% so get next symptom and
% add to list on backtracking
getSymptoms(Symptoms0),
Symptoms = [Symptom|Symptoms0]
;
% Symptom was invalid
% so warn user of invalid symptom and what they input
% and get next symptom.
% Do not add invalid Symptom to list on backtracking.
format('Invalid symptom: `~w''~n',[Symptom]),
getSymptoms(Symptoms0),
Symptoms = Symptoms0
).
由于输入的值是字符串,症状是症状/2
事实中的原子,因此需要将输入转换为原子以进行比较。这是通过使用
如果症状无效,则向用户提供反馈。使用它比使用它更好,因为它可以让您更好地控制输出
format('Invalid symptom: `~w''~n',[Symptom])
如果为输入了无效值作为症状,则不应将其添加到列表中。这是一个典型的if/then类型的场景,在Prolog中使用。这是标准模板
(
<conditional>
->
<true branch>
;
<false branch>
)
请注意,还有一个条件,它读取症状/2
事实,忽略复合结构的第一部分,即\u
,并将输入症状与事实中的症状相匹配。这是因为比较已经完成,但它是通过统一完成的,而不是使用比较谓词,例如
真正的分支与以前一样
getSymptoms(Symptoms0),
Symptoms = [Symptom|Symptoms0]
然而,错误的分支是
format('Invalid symptom: `~w''~n',[Symptom]),
getSymptoms(Symptoms0),
Symptoms = Symptoms0
请注意,无效的症状
没有添加到带有[Symptom | Symptoms0]
的列表中,而且两个分支(true和false)都应该更新相同的变量症状
,在false分支中,这些变量是通过症状=症状0
完成的,而不是赋值,而是(统一)
valid\u symptom/2
的代码本可以与getSymptoms/1
内联,但我将其拔出,以便您可以查看如何完成,以备将来需要
运行示例:
?- getSymptoms(Symptoms).
Please enter symptoms now, enter "Done" when finished: wrong
Invalid symptom: `wrong'
Please enter symptoms now, enter "Done" when finished: headache
Please enter symptoms now, enter "Done" when finished: malaise
Please enter symptoms now, enter "Done" when finished: headache
Please enter symptoms now, enter "Done" when finished: Done
Symptoms = [headache, malaise, headache].
?- getSymptoms(Symptoms).
Please enter symptoms now, enter "Done" when finished: headache
Please enter symptoms now, enter "Done" when finished: malaise
Please enter symptoms now, enter "Done" when finished: headache
Please enter symptoms now, enter "Done" when finished: Done
Symptoms = [malaise, headache].
下面是在构建列表时删除重复项的下一个变体
getSymptoms(Result) :-
getSymptoms_helper([],Result).
getSymptoms_helper(Symptoms,Result) :-
write('Please enter symptoms now, enter "Done" when finished: ' ),
read_string(user, "\n", "\r", _, Response),
(
Response == "Done"
->
Result = Symptoms
;
atom_string(Symptom,Response),
valid_symptom(Symptom,Symptoms,Result)
).
valid_symptom(Symptom,Symptoms,Result) :-
(
memberchk(Symptom,Symptoms)
->
% Symptom was a duplicate
% Do not add duplicate Symptom to list.
getSymptoms_helper(Symptoms,Result)
;
(
symptom(_,Symptom)
->
% Symptom was valid
% so get next symptom and
% add to list.
getSymptoms_helper([Symptom|Symptoms],Result)
;
% Symptom was invalid
% so warn user of invalid symptom and what they input
% and get next symptom.
% Do not add invalid Symptom to list.
format('Invalid symptom: `~w''~n',[Symptom]),
getSymptoms_helper(Symptoms,Result)
)
).
这里的主要变化是累加器症状
通过谓词进行线程化,以便可以构建有效症状列表并用于测试下一个输入值。由于累加器需要在开始时初始化,因此前面的谓词重命名为getSymptoms\u helper
,以便可以使用
getSymptoms_helper([],Result)
请注意传递到的[]
getSymptoms_helper(Symptoms,Result)
因此,将症状的初始值设置为[]
当输入Done
时,列表与Result
统一,并在反向链接时传回。通常情况下,变量将被命名为symples0
和symples
,但我以这种方式保存它们,以便更容易理解。另一方面,可能会有变量症状
、症状
和症状0
,但一旦你习惯了它们,就更容易理解
检查重复项时使用的是比检查更好的方法。这再次为混合添加了另一个条件
运行示例:
?- getSymptoms(Symptoms).
Please enter symptoms now, enter "Done" when finished: wrong
Invalid symptom: `wrong'
Please enter symptoms now, enter "Done" when finished: headache
Please enter symptoms now, enter "Done" when finished: malaise
Please enter symptoms now, enter "Done" when finished: headache
Please enter symptoms now, enter "Done" when finished: Done
Symptoms = [headache, malaise, headache].
?- getSymptoms(Symptoms).
Please enter symptoms now, enter "Done" when finished: headache
Please enter symptoms now, enter "Done" when finished: malaise
Please enter symptoms now, enter "Done" when finished: headache
Please enter symptoms now, enter "Done" when finished: Done
Symptoms = [malaise, headache].
相关问题:。@GuyCoder正在看这个。你能提供的任何例子都会有帮助,因为这是我第一次使用prolog,我需要学习它。哇,谢谢你花这么多时间在这上面。我有几个问题是,我已经走上了正轨,你是否有这个“有效的症状(症状,症状):-(症状(,症状)…)但我试图保持症状与哪种疾病相关。我尝试这样的检查症状(症状,症状):-(症状(疾病,症状)->getSymptoms(症状0),症状=[症状|症状0],Diseases=[Disease | Diseas0]…“这是一种方法吗?@user10876930我不会这样做,因为您正在创建两个单独的列表,例如症状=[Symptom | Symptoms0]
,疾病=[Disease | Diseas0].
要求两者始终同步。如果从其中一个项目中删除某个项目,则会出现问题。最好使用元组或更好的复合术语创建列表,例如,[症状(带状疱疹、头痛)、症状(带状疱疹、瘙痒)]
。我知道这看起来像是在复制症状事实中的值,但效果会更好。你应该作为一个单独的问题来提问,并获得更多的分数。@user10876930如果你问了这个问题,请思考你如何需要下一部分的数据,并在问题中解释。如果你以你写的方式提问,我会在这里,当你有几种疾病的几种症状时,数据可以在提取时以不同的方式排列,避免重新排列的麻烦,例如[XYZ,[ABC,DEF],UVW,[GHI,JKL,MNO]]
其中第一部分是疾病,第二部分是症状列表。好的,我明白你关于必须保持两个列表同步的意思。我现在将查看元组/复合列表。再次感谢你花时间回答问题并提供解释!