如何将列表替换为包含要替换的变量的另一个列表。例如
rep([x, d, e, z, x, z, p], [x=z, z=x, d=c], R).
R = [z, c, e, x, z, x, p]
x到z和z在更换后不会改变。
到目前为止,我只做了没有列表的那个
rep([], _, []).
rep(L1, H1=H2, L2) :-
rep(L1, H1, H2, L2).
rep([],_,_,[]).
rep([H|T], X1, X2, [X2|L]) :-
H=X1,
rep(T,X1,X2,L),
!.
rep([H|T],X1,X2,[H|L]) :-
rep(T,X1,X2,L).
答案 0 :(得分:1)
如果你使用SWI-Prolog,在那里找到模块lambda.pl:http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/lambda.pl你可以写:
:- use_module(library(lambda)).
rep(L, Rep, New_L) :-
maplist(\X^Y^(member(X=Z, Rep)
-> Y = Z
; Y = X), L, New_L).
答案 1 :(得分:1)
您应该尝试使代码更简单:
rep([], _, []).
rep([X|Xs], Vs, [Y|Ys]) :-
( memberchk(X=V, Vs) -> Y = V ; Y = X ),
rep(Xs, Vs, Ys).
当然,请注意检查变量值的惯用方法(通过memberchk / 2)。
仍然是一种更惯用的方式:转换列表它是几种语言的基本构建块,Prolog也不例外:
rep(Xs, Vs, Ys) :- maplist(repv(Vs), Xs, Ys).
repv(Vs, X, Y) :- memberchk(X=V, Vs) -> Y = V ; Y = X .
答案 2 :(得分:1)
首先,我们尝试在对Key
对列表中找到单个K-V
。
额外的参数可以提高搜索成功率。
pairs_key_firstvalue_t([] ,_ ,_ ,false).
pairs_key_firstvalue_t([K-V|KVs],Key,Value,Truth) :-
if_(K=Key,
(V=Value, Truth=true),
pairs_key_firstvalue_t(KVs,Key,Value,Truth)).
接下来,我们需要处理“未找到”案例:
assoc_key_mapped(Assoc,Key,Value) :-
if_(pairs_key_firstvalue_t(Assoc,Key,Value),
true,
Key=Value).
最后,我们使用meta-predicate maplist/3
:
?- maplist(assoc_key_mapped([x-z,z-x,d-c]), [x,d,e,z,a,z,p], Rs).
Rs = [z,c,e,x,a,x,p]. % OK, succeeds deterministically
答案 3 :(得分:1)
通过移动"递归部分"来改进this answer。进入meta-predicate find_first_in_t/4
:
:- meta_predicate find_first_in_t(2,?,?,?).
find_first_in_t(P_2,X,Xs,Truth) :-
list_first_suchthat_t(Xs,X,P_2,Truth).
list_first_suchthat_t([] ,_, _ ,false).
list_first_suchthat_t([E|Es],X,P_2,Truth) :-
if_(call(P_2,E),
(E=X,Truth=true),
list_first_suchthat_t(Es,X,P_2,Truth)).
要填写"缺少的部分",我们定义key_pair_t/3
:
key_pair_t(Key,K-_,Truth) :-
=(Key,K,Truth).
根据find_first_in_t/4
和key_pair_t/3
,我们可以像这样写assoc_key_mapped/3
:
assoc_key_mapped(Assoc,Key,Value) :-
if_(find_first_in_t(key_pair_t(Key),_-Value,Assoc),
true,
Key=Value).
那么,OP的用例是否仍然有效?
?- maplist(assoc_key_mapped([x-z,z-x,d-c]), [x,d,e,z,a,z,p], Rs).
Rs = [z,c,e,x,a,x,p]. % OK. same result as before
以find_first_in_t/4
memberd_t(X,Xs,Truth) :- % memberd_t/3
find_first_in_t(=(X),_,Xs,Truth).
:- meta_predicate exists_in_t(2,?,?). % exists_in_t/3
exists_in_t(P_2,Xs,Truth) :-
find_first_in_t(P_2,_,Xs,Truth).
答案 4 :(得分:0)
我觉得你的代码很混乱。首先,你有rep/3
和rep/4
,但是没有一个在你传递变量绑定列表的第二个位置有一个列表。 H1=H2
不能匹配列表,而且这是检查第二个参数的唯一rep/3
子句。如果这是一个课堂作业,看起来你有点落后,我建议你花一些时间在之前的材料上。
解决方案比你想象的更简单:
rep([], _, []).
rep([X|Xs], Vars, [Y|Rest]) :- member(X=Y, Vars), rep(Xs, Vars, Rest).
rep([X|Xs], Vars, [X|Rest]) :- \+ member(X=_, Vars), rep(Xs, Vars, Rest).
我们使用member/2
在列表中找到“变量绑定”(在引号中,因为它们是原子而不是真正的Prolog变量)。如果它在列表中,Y是替换,否则我们继续使用X.并且您看到这具有期望的效果:
?- rep([x, d, e, z, x, z, p], [x=z, z=x, d=c], R).
R = [z, c, e, x, z, x, p] ;
false.
使用“或”直接(并为我们保存一个选择点)可以提高效率:
rep([], _, []).
rep([X|Xs], Vars, [Y|Ys]) :-
(member(X=Y, Vars), ! ; X=Y),
rep(Xs, Vars, Ys).
请参阅:
?- rep([x, d, e, z, x, z, p], [x=z, z=x, d=c], R).
R = [z, c, e, x, z, x, p].
答案 5 :(得分:0)
将连接词或谓词转换为真值函数的方法,即对于arity n的连接词或谓语词XX,尝试使用域中的最后一个参数来生成arity n + 1的谓词XX_t {true,false如果这种方法基于ISO标准,则存在严重的限制。
一个典型的限制是这些谓词不能轻易地删除(;)/ 2的分支。正常切割(!)也会影响(;)/ 2的周围,因为(;)/ 2被切割为透明。
需要的是局部剪切(sys_local_cut),它可以在本地影响剪切透明谓词。所以我猜这是所有这些看起来的盲点,看我有一个XX_t谓词,但它留给了许多选择点。
问题是局部剪切(sys_local_cut)不符合ISO标准。但我想如果XX_t connnectives的开发者会有这样的手段,它将达到与原始XX连接相同的选择点行为。
再见