我一直在尝试编写一些带有值列表的代码,并删除仅列在列表中的所有值,非重复项:
dbltaker([], []).
dbltaker([H | X], Y):-
\+mem(H, X),
dbltaker(X, Y).
dbltaker([H | X], [H | Y]):-
mem(H, X), !,
dbltaker(X, Y).
dbltaker([H | X], [H | Y]):-
mem(H, Y),
dbltaker(X, Y).
mem(H, [H | _]).
mem(H, [_ | T]):-
mem(H, T).
我遇到的麻烦是,在将非重复移动到另一个列表之后,它的重复不再是重复,因此不会移动到列表中。例如,列表[1,1,1,2,2,3]给出[1,1,2]作为输出,因为最后一个和两个不被视为重复,因为它们不再是它们的成员尾巴,我无法检查它们是否是新列表的成员,因为它尚未实例化。
有解决方法吗?
感谢。
答案 0 :(得分:-1)
我认为更简单的方法应该是传递给原始列表,以便能够检查元素何时重复。
dbltaker(L, R) :- dbltaker(L, L, R).
dbltaker([], _L, []).
dbltaker([H|T], L, [H|R]) :- at_least_2(H, L), !, dbltaker(T, L, R).
dbltaker([_|T], L, R) :- dbltaker(T, L, R).
服务谓词at_least_2(H, L)
可以很容易地实现......
答案 1 :(得分:-1)
我就是这样做的:
首先,检查列表成员资格:
exists_in( A , [A|_] ) :- ! .
exists_in( A , [_|B] ) :- exists_in(A,B) .
然后是条件添加。如果X不包含在Y中,则将X添加到Y,得到Z:
add_if_not_exists( X , Z , Z ) :- exists(X,T) , ! .
add_if_not_exists( X , Y , [X|Y] ) .
使用累加器(播种到空列表[]
)来构建一组不同元素的工作谓词,它完成了艰苦的工作:
dedupe( [] , Z , Z ) . % if the source list is exhausted, we're done: the accumulator is the set of distinct list members.
dedupe( [X|Xs] , Y , Z ) :- % otherwise...
add_if_not_exists(X,Y,T) , % - add X to the accumulator if it's not already there.
dedupe(Xs,T,Z) % - and recurse down.
. % Easy!
最后,公共接口谓词只调用worker谓词:
dedupe( Xs, Ys ) :- % dedupe a list
dedupe( Xs, [] , Ys ) % by invoking the helper predicate with the accumulator seeded with the empty set.
. %
注意: worker谓词以逆序构建重复数据删除列表。如果订单很重要,那么撤销列表是微不足道的:
rev( [] , [] ) .
rev( [X|Xs] , Rs ) :- rev( Xs , [X|Rs] ) .
只需修改公共接口即可进行撤消:
dedupe1( Xs, Ys ) :- % dedupe a list
dedupe( Xs, [] , T ) , % by invoking the helper predicate with the accumulator seeded to the empty set.
rev(T,Ys) % and reversing the result.
. %