Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
List 序言:用其他列表的重复元素构建一个列表_List_Prolog_Meta Predicate - Fatal编程技术网

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
    包含在广泛可用的。让我们用那个

  • 让我们重新运行OP给出的查询

    ?- rep_elements([a,b,c,a,b,d],Xs). Xs = [a,b] ; false. ?-rep_元素([a,b,c,a,b,d],Xs)。 Xs=[a,b] ; 错。
  • 好的!我们结束了吗?不完全是!考虑下面的查询和我们得到的答案:

    ?- rep_elements([a,a,a,a,b],Xs). Xs = [a,a,a] % (1) duplicate items are retained ; Xs = [a,a,a] % (2) redundant answer ; Xs = [a,a,a] % (2) ; Xs = [a,a,a] % (2) ; Xs = [a,a,a] % (2) ; Xs = [a,a,a] % (2) ; false. % (3) leaves behind useless choicepoint ?-rep_元素([a,a,a,b],Xs)。 Xs=[a,a,a]%(1)保留重复项 ; Xs=[a,a,a]%(2)冗余答案 ; Xs=[a,a,a]%(2) ; Xs=[a,a,a]%(2) ; Xs=[a,a,a]%(2) ; Xs=[a,a,a]%(2) ; 错.%(3) 留下无用的选择点
  • 下一步是什么?退后一步,按照规范工作


  • 首先,我建议我们使用一个更具描述性的谓词名称,
    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).