首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何将列表与数据库Prolog进行比较

如何将列表与数据库Prolog进行比较
EN

Stack Overflow用户
提问于 2019-02-15 20:11:29
回答 1查看 143关注 0票数 1

我有一个事实数据库,其中有类似这个片段的条目。

代码语言:javascript
复制
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).

然后,我有一个谓词,它从用户那里获得一系列症状。

代码语言:javascript
复制
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]
    ).

我的问题是如何将用户症状列表与症状事实第二个原子进行比较,然后将疾病添加到另一个列表中?例如,用户进入发烧状态。由于发烧是带状疱疹的症状,它会把带状疱疹列入名单。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-02-15 21:23:15

这将工作,但允许重复的症状被输入。我现在发布它,以便您可以看到第一部分的转换,并将张贴部分,没有重复,当我得到工作。

代码语言:javascript
复制
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
    ).

由于输入的值是字符串,而症状是symptom/2事实中的原子,因此需要将输入转换为原子进行比较。这是使用字符串/2完成的

代码语言:javascript
复制
atom_string(Symptom,Response) 

若要向用户提供症状无效时的反馈,请使用格式/2。它比写/1更好,因为它使您对输出有更多的控制。

代码语言:javascript
复制
format('Invalid symptom: `~w''~n',[Symptom])

如果输入无效值作为症状,则不应将其添加到列表中。这是典型的if/然后类型的场景,在Prolog中是用->/2完成的。以下是标准模板

代码语言:javascript
复制
(
    <conditional>
->
    <true branch>
;
    <false branch>
)

条件是

代码语言:javascript
复制
symptom(_,Symptom)

还请注意,它读取symptom/2事实,忽略复合结构的第一部分,即_,并将输入症状与事实中的症状匹配。这是通过比较完成的,但是它是通过统一完成的,而不是通过=/2这样的比较谓词完成的。

真正的分支和以前一样。

代码语言:javascript
复制
getSymptoms(Symptoms0),
Symptoms = [Symptom|Symptoms0]

然而,假分支是

代码语言:javascript
复制
format('Invalid symptom: `~w''~n',[Symptom]),
getSymptoms(Symptoms0),
Symptoms = Symptoms0

请注意,无效的Symptom没有用[Symptom|Symptoms0]添加到列表中,而且两个分支(真和假)都应该更新相同的变量Symptoms,在假分支中,Symptoms是用Symptoms = Symptoms0完成的,而Symptoms = Symptoms0不是赋值,而是=/2 (统一)。

valid_symptom/2的代码可能包含了getSymptoms/1,但我提取了它,这样您就可以看到它是如何完成的,以防将来需要这样做。

示例运行:

代码语言:javascript
复制
?- 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].

下面是在构建列表时删除重复项的下一个变体。

代码语言:javascript
复制
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)
        )
    ).

这里的主要变化是,累加器Symptoms通过谓词进行线程化,以便可以构建有效症状列表并用于测试下一个输入值。由于累加器需要在开始时初始化,所以前面的谓词重命名为getSymptoms_helper,以便可以用

代码语言:javascript
复制
getSymptoms_helper([],Result)

注意传递给[]

代码语言:javascript
复制
getSymptoms_helper(Symptoms,Result)

因此,将Symptoms的初始值设置为[]

当输入Done时,列表将与Result统一,并返回回链。通常情况下,变量将被命名为Symptoms0Symptoms,但是我保留了它们,因此它们更易于跟踪。其他明智的方法是变量SymptomSymptomsSymptoms0,但是一旦您习惯了它们,就会更容易理解它们。

对重复项的检查是使用成员k/2完成的,这比使用成员/2进行检查要好。这再次为混合添加了另一个条件。

示例运行:

代码语言:javascript
复制
?- 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].
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54716395

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档