4

我只需要删除列表中的一个事件。其实不管是第一个还是最后一个。需要删除一场比赛。

我无法理解为什么以下内容无法按预期工作。

deleteOne(_,[],[]).

deleteOne(Term, [Term|Tail], Result) :- 
    deleteOne(Term, [], [Result|Tail]), !.

deleteOne(Term, [Head|Tail], [Head|TailResult]) :- 
    deleteOne(Term, Tail, TailResult), !.

输出

41 ?- deleteOne(5,[2,3,1,5,2,3,1],X).
X = [2, 3, 1, 5, 2, 3, 1].

当我用空字符串或一些随机字符串替换术语时,它会起作用。

 deleteOne(Term, [Term|Tail], Result) :- 
    deleteOne("", Tail, Result), !.

输出

41 ?- deleteOne(5,[2,3,1,5,2,3,1],X).
X = [2, 3, 1, 2, 3, 1].

但由于许多原因,我认为这不是最好的解决方案。不是针对我当前的问题,而是针对更长的列表。或者如果一个列表包含空字符串 - 不知道这在 Prolog 中是否可行。

为什么第一个示例不起作用?还有哪些其他解决方案?

4

2 回答 2

3

你的第一个不起作用,因为这没有多大意义:

deleteOne(Term, [Term|Tail], Result) :- 
    deleteOne(Term, [], [Result|Tail]), !.

这意味着下一个结果必须以当前结果为中心。

更好的解决方案是:

delete_one(_, [], []).
delete_one(Term, [Term|Tail], Tail).
delete_one(Term, [Head|Tail], [Head|Result]) :-
  delete_one(Term, Tail, Result).

如果您希望它具有决定性,请在第二个子句上添加一个cut。照原样,它可以这样做:

?- delete_one(2, [1, 2, 3, 1, 2, 3], X).
X = [1,3,1,2,3] ? ;
X = [1,2,3,1,3] ? ;
X = [1,2,3,1,2,3] ? ;    
no
于 2013-04-07T00:14:21.423 回答
0

要从列表 L 中仅删除第一次出现的项目 X。这里我使用了剪切操作。

delete(X,[X|T],T):-!.
delete(X,[Y|T],[Y|T1]):-delete(X,T,T1).
于 2020-01-29T14:39:18.690 回答