问题描述
我处于以下情况:我有一个列表,我只想删除最后一个元素.
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 = [].
在达到基本情况时,没有结束列表与空列表 []统一,执行回溯后,没有结束保留为空列表.
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:
- 在调用删除最后一个元素的谓词之前,对列表中的元素数进行计数.
- 通过递归进行迭代,并每次减少元素数量的值
- 如果元素的数目为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列表中删除最后一个元素?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!