从列表Prolog中选择元素

时间:2018-10-17 02:40:13

标签: prolog

我在编写一个从列表中选择每个元素的函数时遇到了麻烦。我要我的函数执行的操作是接收一个列表,并返回选择的元素,以及不包含该元素的新列表。该函数的调用如下所示:

   pickElement([LIST], PICKEDELEMENT, NEWLIST).

因此,如果我传入列表[1,2,3],我希望函数传递三遍,并且输出如下所示:

   PICKEDELEMENT = 1
   NEWLIST = [2,3]

   PICKEDELEMENT = 2
   NEWLIST = [1,3]

   PICKEDELEMENT = 3
   NEWLIST = [1,3]

我编写了以下函数,但是在选择了元素之后,它将其从我不想要的列表中删除。

   pickELEMENT([X|XREST],X,XREST).
   pickELEMENT([X|XREST],PICKEDELEMENT,NEWLIST) :- 
   pick(XREST,PICKEDELEMENT,NEWLIST).

我很难获得想要的输出。如果有人可以告诉我我需要做什么,那将不胜感激。

谢谢。

1 个答案:

答案 0 :(得分:1)

您的实施朝着正确的方向发展。它包含一些错误,例如,您定义了谓词pickELEMENT/2,但随后旨在调用pick/2。通过一些“重写”,我们获得您可能想要实现的谓词:

pick([X|XRest], X, XRest).
pick([X|XRest], Element, NewList) :- 
    pick(XRest, Element, NewList).

现在仍然存在语义错误:在第二个子句中,第三个参数是NewList,因此这意味着我们“忽略”了原始列表中的X。是的,在您的第二个子句中,您没有 pick X,但这意味着它应该是NewList的一部分,因此我们在递归调用的结果前面加上X,例如:

pick([X|XRest], X, XRest).
pick([X|XRest], Element, [X|NewList]) :- 
    pick(XRest, Element, NewList).

上面的内容可以改进,在这里我们将解压缩“ cons”列表元素两次:一次在第一个子句中,一次在第二个子句中。我们可以通过实现pick/4谓词,然后将pick/3重定向到pick/4来防止这种低效率:

pick([H|T], X, NewList) :-
    pick(T, H, X, NewList).

pick(XRest, X, X, XRest).
pick([X2|XRest], X, Element, [X|NewList]) :- 
    pick(XRest, X2, Element, NewList).