Prolog使用累加器查找列表中的元素

时间:2014-10-06 02:44:12

标签: prolog

我正在尝试理解累加器,所以我希望这个实现包含它们。 我已经想过如何搜索一个简单的列表。 这会计算给定元素的出现次数:

find(Element,[],A,A).
find(Element, [H|Tail], A, N) :- Element = H, A1 is A + 1,
find(Element, Tail, A1, N). 
find(Element, [H|Tail], A, N) :- find(Element, Tail, A, N).

现在我怎样才能让它适用于嵌套列表呢?

1 个答案:

答案 0 :(得分:1)

您应该只是向匹配器添加另一个项目,以便如果H也是一个列表,则首先计算出现次数:

find(Element,[],A,A).
find(Element, [Element|Tail], A, N) :-
    !,
    A1 is A + 1,
    find(Element, Tail, A1, N).
find(Element,[[H|T]|Tail],A,N) :-
    !,
    find(Element,[H|T],A,R),
    find(Element,Tail,R,N).
find(Element, [H|Tail], A, N) :-
    find(Element, Tail, A, N).

通过在列表递归之前放置Element(第二个子句)的相等性,您还可以搜索列表中的列表。换句话说:

find([1,2],[[1,2],[3],4,[1,2]])

将返回2

您使用剪切(!)来阻止Prolog回溯。


  
    

提示:如果可能的话,不会在正文(Element = H)中统一。只需在头部重用相同的变量(find(Element,[Element|Tail],A,N))。许多Prolog编译器能够比第一种情况更好地优化后者。

  

  
    

提示:使用削减。您可以更频繁地使用剪切来防止Prolog产生非确定性。例如,如果您计算5[5,1,2,5]的出现次数,则可以提出210,因为您从未在最后一条中指明H 不等于Element。通过在前一个条款中放置一个剪辑,Prolog解释器将永远不会回溯这个。