如何从 Prolog 的列表中删除最后一个元素? [英] How to delete the last element from a list in Prolog?

查看:23
本文介绍了如何从 Prolog 的列表中删除最后一个元素?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我处于以下情况:我有一个列表,我只想从中删除最后一个元素.

I am in the following situation: I have a list and I would to delete from it only the last element.

我已经实施了以下规则(效果不佳):

I have implement the following rule (that don't work well):

deleteLastElement([Only],WithoutLast) :-
    !,
    delete([Only],Only,WithoutLast).
deleteLastElement([_|Tail],WithoutLast) :-
    !,
    deleteLastElement(Tail,WithoutLast).

问题是当我调用它时,列表中的所有元素都被删除了,实际上如果我执行以下语句我得到:

The problem is that when I call it, all the element in the list are deleted, in fact if I execute the following statement I obtain:

[debug]  ?- deleteLastElement([a,b,c], List).
List = [].

查看痕迹我认为很清楚导致此问题的原因:

Looking at the trace I think that is clear the cause of this problem:

[trace]  ?- deleteLastElement([a,b], List).
   Call: (7) deleteLastElement([a, b], _G396) ? creep
   Call: (8) deleteLastElement([b], _G396) ? creep
   Call: (9) lists:delete([b], b, _G396) ? creep
   Exit: (9) lists:delete([b], b, []) ? creep
   Exit: (8) deleteLastElement([b], []) ? creep
   Exit: (7) deleteLastElement([a, b], []) ? creep
List = [].

当达到基本情况时,WithoutLast 列表与 空列表 [] 统一,当执行回溯时,WithoutLast 仍然保持空列表.

When the base case is reached, the WithoutLast list is unified with the empty list [] and when backtracking is performed the WithoutLast still remain the empty list.

这不好.

我正在考虑通过以下操作来实现它:

I was thinking to implement it doing the following operation:

  1. 在调用删除最后一个元素的谓词之前计算列表中的元素个数.
  2. 递归迭代,每次递减元素个数的值
  3. 如果元素个数为 0,则表示这是最后一个元素,所以我将其从原始列表中删除

但这在我看来不是很清楚,也不是很好,我想知道是否有针对此问题的声明式良好解决方案.

But this seems to me not clear and not so good, I would know if there is a declarative good solution for this problem.

推荐答案

为了防止创建无用的选择点,请使用滞后以从第一个参数索引中受益:

To prevent the creation of useless choicepoints, use lagging to benefit from first argument indexing:

list_butlast([X|Xs], Ys) :-                 % use auxiliary predicate ...
   list_butlast_prev(Xs, Ys, X).            % ... which lags behind by one item

list_butlast_prev([], [], _).
list_butlast_prev([X1|Xs], [X0|Ys], X0) :-  
   list_butlast_prev(Xs, Ys, X1).           % lag behind by one

示例查询:

?- list_butlast([], Xs).
false.

?- list_butlast([1], Xs).
Xs = [].                                    % succeeds deterministically

?- list_butlast([1,2], Xs).
Xs = [1].                                   % succeeds deterministically

?- list_butlast([1,2,3], Xs).
Xs = [1,2].                                 % succeeds deterministically

另一个方向呢?

?- list_butlast(Xs, []).
Xs = [_A].

?- list_butlast(Xs, [1,2,3]).
Xs = [1,2,3,_A].

最一般的查询呢?

?- list_butlast(Xs, Ys).
   Xs = [_A]            , Ys = []
;  Xs = [_A,_B]         , Ys = [_A]
;  Xs = [_A,_B,_C]      , Ys = [_A,_B]
;  Xs = [_A,_B,_C,_D]   , Ys = [_A,_B,_C]
;  Xs = [_A,_B,_C,_D,_E], Ys = [_A,_B,_C,_D]
⋯

这篇关于如何从 Prolog 的列表中删除最后一个元素?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆