从列表中移除第一个出现的元素 - Prolog

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].

当我将term替换为空字符串或随机字符串时,它就能正常工作。

 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中是否可能。

为什么第一个例子不能工作?还有其他解决方案吗?

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).

如果您想让它有决定性,可以在第二个子句上加一个分割线。目前状态下,它可以做到这一点:

?- 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

0

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

delete(X,[X|T],T):-!.
delete(X,[Y|T],[Y|T1]):-delete(X,T,T1).

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接