如何从prolog中的列表中删除所有重复项

时间:2014-01-10 18:08:47

标签: list prolog duplicates

我有一个列表,让我们说X=[a,b,c,d,c,e,d],如何删除每个字符中的一个,这样唯一的答案仍然是X1=[c,d]

我有一堆只有字母字母的列表,我需要一个命令,如果列表中包含这样的字符,将删除每一个字母,如果没有该字母则不执行任何操作。

我已尝试使用selectchk/3,但它仅适用于特定情况。

例如,如果我有列表X=[a,b,c,d,d,e,e,f,f,g,h], 我可以写selectchk(d,X,X1), selectchk(e,X1,X2), selectchk(f,X2,X3)等等。

正如我所说,这仅适用于特定情况,但如果我添加一般谓词,请说我每个字母都有selectchk/3,但是,例如, 新列表为X1=[a,b,c,d,d],我使用selectchk(f,X,X3), 命令失败,并且没有命名下一个列表X3,所以下一个命令检查字母' G'列表X3中的列表无法运行,因为没有此类列表。如果一个失败,是否有可能做OR命令?

X=[a,a,c,d,d,e]

selectchk(a,X,X1)或(如果没有)append([],X,X1),selectchk(b,X1,X2)或(如果没有' b'),append([],X2,X3)等。

由于

1 个答案:

答案 0 :(得分:1)

有几种方法可以做到这一点。我认为selectchk/3构成了一个解决方案的良好基础,这实际上是对#34;自动化"你试图手动做什么并使用递归:

select_each_one(L, R) :-
    sort(L, PickList),
    select_each_one(L, PickList, R).
select_each_one(L, [H|T], R) :-
    selectchk(H, L, R1),
    select_each_one(R1, T, R).
select_each_one(L, [], L).

sort提供了一个"选项列表"仅包含原始列表中每个元素中的一个。然后select_each_one/3谓词在原始列表的每次迭代中对每个元素执行selectchk

?- select_each_one([a,b,c,d,c,e,d], L).
L = [c, d] ;
false.

?- select_each_one([a,b,c,d,d,e,e,f,f,g,h], L).
L = [d, e, f] ;
false.

另一种方法是一次将列表复制到一个元素上,但跟踪我们是否看过该元素:

select_each_one(L, R) :-
    select_each_one(L, [], R).
select_each_one([H|T], Seen, R) :-
    (   member(H, Seen)
    ->  R = [H|R1], select_each_one(T, Seen, R1)
    ;   select_each_one(T, [H|Seen], R)
    ).
select_each_one([], _, []).