List 序言:用其他列表的重复元素构建一个列表
我需要构造一个接收列表的谓词,检查哪些元素是重复的,并返回其他列表。例如:List 序言:用其他列表的重复元素构建一个列表,list,prolog,meta-predicate,List,Prolog,Meta Predicate,我需要构造一个接收列表的谓词,检查哪些元素是重复的,并返回其他列表。例如: ?- rep_elements([a,b,c,a,b,d], Xs). Xs = [a,b]. 我开始构建一个基本结构,但我现在不知道如何完成这个谓词,或者这是否是更好的方法: exists(Elem, [Elem|_]). exists(Elem, [H|T]) :- exists(Elem, T). rep_elements([], []). rep_elements([H|T], [Y|Z]) :-
?- rep_elements([a,b,c,a,b,d], Xs).
Xs = [a,b].
我开始构建一个基本结构,但我现在不知道如何完成这个谓词,或者这是否是更好的方法:
exists(Elem, [Elem|_]).
exists(Elem, [H|T]) :-
exists(Elem, T).
rep_elements([], []).
rep_elements([H|T], [Y|Z]) :-
exists(H, T),
rep_elements(T, Z).
有什么建议吗?rep_elements/2缺少对非重复元素的处理
如果exists/2在删除找到的重复项后也会“返回”列表T,那么我们可以使用清理后的列表进行递归,任务就完成了。当然,exists/2应该变成exists/3,也许可以重命名为更好、更具描述性的名称。让我们一步一步地重新编写代码
存在/2
包含在广泛可用的。让我们用那个
首先,我建议我们使用一个更具描述性的谓词名称,
list\u uniqdups
我们根据以下内容定义list\u uniqdups/2
:
示例查询:
?- list_uniqdups([a,b,c,a,b,d],Xs). % query as given by the OP
Xs = [a,b]. % expected result
?- list_uniqdups([a,c,b,a,b,d],Xs). % similar query
Xs = [a,b]. % same result
?- list_uniqdups([b,c,a,a,b,d],Xs). % now, `b` comes before `a`
Xs = [b,a]. % retain the original order
?- list_uniqdups([a,a,a,a,b],Xs).
Xs = [a]. % remove all duplicates
?-列出联合体([a,b,c,a,b,d],Xs)。%由OP给出的查询
Xs=[a,b].%预期结果
?-列出联合体([a,c,b,a,b,d],Xs)。%类似查询
Xs=[a,b].%同样的结果
?-列出联合体([b,c,a,a,b,d],Xs)。%现在,`b`在`a'之前`
Xs=[b,a].%保留原订单
?列出联合体([a,a,a,b],Xs)。
Xs=[a].%删除所有重复项
请注意,以上所有查询都以确定方式成功。您可以递归地检查列表的头部是否位于列表的尾部,然后将其添加到结果中。 您的解决方案可以修改为:
exists(Elem, [Elem|_]).
exists(Elem, [H|T]) :-
exists(Elem, T).
/* IF you get empty list*/
rep_elements([], []).
/* If repetition found in list then joining it to head of list*/
rep_elements([H|T], Result) :-
exists(H, T),
rep_elements(T, [H|Result]).
/* If head of list is not found in the Tail of list*/
rep_elements(H|T, Result):-
not(exists(H,T)),
rep_elements(T,Result).
这应该有效。可能重复@false。好吗?(应该比以前更体面一些)这是一个非常有趣的解决方案。我将更仔细地研究元谓词,以了解是什么使这个解决方案成为可能。谢谢@罗德里戈。尽一切办法!元谓词支持惯用的高级编程风格。关于元谓词,我建议您首先查看
maplist/2
(更多信息:and)。学习如何使用它以及它是如何工作的。然后返回并研究t部分/4
。只是为了解释一下,我通常使用自己的谓词(exists/2
而不是member/2
等等),因为这样我可以在调试时一步一步地检查正在运行的谓词,而内置谓词是不可能的。
list_uniqdups([],[]).
list_uniqdups([X|Xs0],Ys0) :-
tpartition(=(X),Xs0,Es,Xs),
if_(Es=[], Ys0=Ys, Ys0=[X|Ys]),
list_uniqdups(Xs,Ys).
?- list_uniqdups([a,b,c,a,b,d],Xs). % query as given by the OP
Xs = [a,b]. % expected result
?- list_uniqdups([a,c,b,a,b,d],Xs). % similar query
Xs = [a,b]. % same result
?- list_uniqdups([b,c,a,a,b,d],Xs). % now, `b` comes before `a`
Xs = [b,a]. % retain the original order
?- list_uniqdups([a,a,a,a,b],Xs).
Xs = [a]. % remove all duplicates
exists(Elem, [Elem|_]).
exists(Elem, [H|T]) :-
exists(Elem, T).
/* IF you get empty list*/
rep_elements([], []).
/* If repetition found in list then joining it to head of list*/
rep_elements([H|T], Result) :-
exists(H, T),
rep_elements(T, [H|Result]).
/* If head of list is not found in the Tail of list*/
rep_elements(H|T, Result):-
not(exists(H,T)),
rep_elements(T,Result).