在列表中搜索名字 - Sicstus Prolog

时间:2013-12-03 21:35:28

标签: prolog

我最近开始与Prolog搞混,但是在列表中遇到了绊脚石。

假设我有一个列表[dom,is,a,man,jane,is,a,woman,mary,is,a,woman],我想创建一个新的女人名列表[jane,mary]。我该怎么做呢?我假设我必须在列表中搜索is,a,woman之后的任何X,但我不知道如何实现这一点。我一直在谷歌搜索几个小时无济于事。如果我有任何:s

,我会发布代码

感谢您的帮助!

2 个答案:

答案 0 :(得分:2)

与描述列表时一样,请考虑使用DCG。例如:

men_women([], [])     --> [].
men_women(Ms, [W|Ws]) --> [W,is,a,woman], men_women(Ms, Ws).
men_women([M|Ms], Ws) --> [M,is,a,man], men_women(Ms, Ws).

示例查询及其结果:

?- phrase(men_women(_, Ws), [dom,is,a,man,jane,is,a,woman,mary,is,a,woman]).
Ws = [jane, mary] ;
false.

此DCG也适用于非常一般的查询,例如:

?- length(Ls, _), phrase(men_women(_, Ws), Ls).
Ls = [], Ws = [] ;
Ls = [_G376, is, a, woman], Ws = [_G376] ;
Ls = [_G376, is, a, man], Ws = [] ;
Ls = [_G376, is, a, woman, _G388, is, a, woman], Ws = [_G376, _G388] .

答案 1 :(得分:1)

% end once the input is empty
find_gender([], _, []).

% Compare the first 4 "entries" in the list.
% Name and Gender are variables, b/c they are written in upper case.
% 'is' and 'a' are atom.
% If the pattern matches, prepend the Name to the results.
find_gender([Name,is,a,Gender|Tail], Gender, [Name|Names]) :-
    % Find further Names in the Tail of the input list.
    find_gender(Tail, Gender, Names).

% The person is not of that Gender.
% You don't need to catch the Name here, b/c it won't be used. 
find_gender([_,is,a,X|Tail], Gender, Names) :-
    X \= Gender, % otherwise you would have wrong results when backtracking
    find_gender(Tail, Gender, Names).

% This is your usage example:
find_women(List, Names) :-
    find_gender(List, woman, Names).
find_men(List, Names) :-
    find_gender(List, man, Names).

反过来也有效:

?- find_women(List, [jane,marry]).
List = [jane, is, a, woman, marry, is, a, woman] ;
false.

如果您的输入列表可以包含其他数据,例如[jane,owns,a,car,jane,is,a,woman,the,car,is,red],那么您只需删除条目,直到通过添加此子句再次找到您的模式:

find_gender([_|T], Gender, Names) :-
    find_gender(T, Gender, Names).

但是这会导致你在回溯时有多个结果,省略了一些名字。在这种情况下,您可能希望在第一个子句中引入剪切(!)。