list - 从列表中删除重复项,同时保留最右边的出现

标签 list prolog prolog-dif

我正在尝试从列表中删除重复项,同时保留最右边的匹配项。例如:[1,2,3,1,2] 被转换为 [3,1,2] 这是我在 Prolog 中的第一次尝试,我不明白我做错了什么。它总是返回 false。这是我的代码:

%nrap(L:list,E:element,S:integer)
%L - the initial list, list of integers
%E - the element, integer
%S - the result, nrap of E in L, S integer
%flow model: (i,i,o),(i,i,i)

nrap([],_,0).
nrap([H|T],E,S):-
    H=E,
    nrap(T,E,S1),
    S is S1+1.
nrap([H|T],E,S):-
    H\=E,
    nrap(T,E,S).

%transform(L:list,L2:list,R:list)
%L - the initial list, list of integers
%L2 - copy of the initial list
%R - the resulted list, without duplicates, list of integers
%flow model: (i,i,o),(i,i,i)

transform([],[],[]).
transform([H|T],L2,[H|R]):-
    nrap(L2,H,S),
    S=1,
    transform(T,L2,R).
transform([H|T],L2,R):-
    nrap(L2,H,S),
    S>1,
    transform(T,L2,R).

最佳答案

我应该纯洁还是不纯洁? 为什么还要考虑牺牲 如果我们可以轻松保存它!
使用 memberd_t/3 if_/3 ,我们定义 list_rset/2和它的左边“双胞胎”list_lset/2 :

list_rset([], []).                     % keep rightmost occurrences
list_rset([E|Es], Rs0) :-
   if_(memberd_t(E, Es),
       Rs0 = Rs,
       Rs0 = [E|Rs]),
   list_rset(Es, Rs).

list_lset([], []).                     % keep leftmost occurrences
list_lset([E|Es], Ls) :-
   post_pre_lset(Es, [E], Ls).         % uses internal auxilary predicate

post_pre_lset([], _, []).            
post_pre_lset([E|Es], Pre, Ls0) :-     % 2nd arg: look-behind accumulator
   if_(memberd_t(E, Pre),
       Ls0 = Ls,
       Ls0 = [E|Ls]),
   post_pre_lset(Es, [E|Pre], Ls).

让我们运行一些查询!

?- _Es = [1,2,3,1,2], list_lset(_Es, Ls), list_rset(_Es, Rs).
Ls = [1,2,3], Rs = [3,1,2].           % succeeds deterministically

在上面的查询中 1先于 2都在列表的开头 [<b>1,2</b>,3,<b>1,2</b>] .
如果1怎么办?先于 2在开头但在结尾跟在后面(例如 [<b>1,2</b>,3,<b>2,1</b>] )?

?-  _Es = [1,2,3,2,1], list_lset(_Es, Ls), list_rset(_Es, Rs).
Ls = [1,2,3], Rs = [3,2,1].          % succeeds deterministically

接下来,我们看一个更一般的list_rset/2使用仅包含变量的列表的目标。
感谢@PauloMoura 的建议!

?- Es = [A,B,C,A,B], list_rset(Es,Rs).
   Es = [C,C,C,C,C], Rs = [    C],     A=B ,               B=C
;  Es = [B,B,C,B,B], Rs = [C,  B],     A=B ,           dif(B,C)
;  Es = [C,B,C,C,B], Rs = [  C,B],               A=C , dif(B,C)
;  Es = [A,C,C,A,C], Rs = [  A,C],           dif(A,C),     B=C
;  Es = [A,B,C,A,B], Rs = [C,A,B], dif(A,B), dif(A,C), dif(B,C).

剩余目标(上图)怎么了? 没有足够的实例化,dif/2是不可判定的。
为了保证逻辑的完整性,执行约束被延迟。

最后,还有一个用例:“输入”列表 Xs具有变量 基本项。

?- Es = [A,B,z], list_rset(Es,Rs).
   Es = [z,z,z], Rs = [    z],     A=B ,               B=z 
;  Es = [B,B,z], Rs = [B,  z],     A=B ,           dif(B,z)
;  Es = [z,B,z], Rs = [  B,z],               A=z , dif(B,z)
;  Es = [A,z,z], Rs = [A,  z],           dif(A,z),     B=z 
;  Es = [A,B,z], Rs = [A,B,z], dif(A,B), dif(A,z), dif(B,z).

关于list - 从列表中删除重复项,同时保留最右边的出现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33265736/

相关文章:

python - 连接不同列表中的两个字符串

python - 重新格式化列表中的字符串 - Python

prolog - 在 Prolog 中创建范围规则

algorithm - 寻找算法来寻找参数以满足给定函数的返回

prolog - 在 Prolog 中定义运算符

list - 消除连续的重复

python - 删除字符串中特定索引处的 'range' 个字符

list - 使用 prolog 再添加两次

prolog - 是否有与 "wildcard"运算符相反的操作符专门用于在 Prolog 中找不到指定的项目?

Python内存消耗: dict VS list of tuples