替换 Prolog 列表中元素的单次出现
Replace a single occurrence of an element in a list in Prolog
我得到了一个列表、一个要替换的元素以及该元素的替换项。我设法对该列表中出现的所有元素执行此操作:
replace([],X,Y,[]).
replace([X|T], X, Y, Z) :-
replace(T, X, Y, Z1),
Z = [Y|Z1].
replace([H|T], X, Y, [H|Z]) :-
replace(T, X, Y, Z).
但是现在我必须只替换该元素的第一次出现。
我的思考过程写作:
replace([X|T], X, Y, Z) :-
replace(T, X, Y, Z1),
Z = [Y|Z1].
是:
Z
是 [X|T],X,Y
的结果,如果 Z1
是 T
、XY
和 Z = [Y|Z1]
的结果。按照相同的思考过程,我尝试编写仅替换第一次出现的元素的函数,如下所示:
一个只实现第一次出现的想法是从 replace/4
进入 replace/5
,如果我更换或不这样,我会计算:
replace_single(L,X,Y,Z) :-
replace2(L,X,Y,0,Z).
replace2([],X,Y,C,[]).
replace2([X|T], X, Y, C, Z) :-
\+ (C = 0),
replace2(T, X, Y, C, Z1),
Z = [X|Z1],
C is 1.
replace2([H|T], X, Y, C, [H|Z]) :-
replace2(T, X, Y, C, Z).
显然不行,我有点迷茫。有人可以告诉我如何解决问题或解决方案本身吗?
我们根据same_length/2
、append/3
, maplist/2
, and prolog-dif:
定义replace/4
replace(Xs,X,Y,Ys) :-
same_length(Xs,Ys),
append(Prefix,[X|Suffix],Xs),
maplist(dif(X),Prefix),
append(Prefix,[Y|Suffix],Ys).
示例查询:
?- replace(Xs,2,two,[1,two,3,4,5,1,2,3,4,5,1,2]).
Xs = [1,2,3,4,5,1,2,3,4,5,1,2]
; false.
?- replace([1,2,3,4,5,1,2,3,4,5,1,2],2,two,Ys).
Ys = [1,two,3,4,5,1,2,3,4,5,1,2]
; false.
另一种方法是使用 DCG:
rep1(X, Y, [Z|T]) --> [Z], { dif(Z, X) }, rep1(X, Y, T).
rep1(X, Y, [Y|T]) --> [X], rest(T).
rep1(_, _, []) --> [].
rest([]) --> [].
rest([H|T]) --> [H], rest(T).
| ?- phrase(rep1(a, 1, L), [a,b,c,a,d]).
L = [1,b,c,a,d] ? ;
| ?- phrase(rep1(a, 1, [x, y, 1, b]), L).
L = [x,y,1,b] ? a
L = [x,y,a,b]
您可以将谓词写成:
replace(X, Y, L, R) :- phrase(rep1(X, Y, R), L).
另一种方法是:-
replace(E1,L1,E2,L2) :-
same_length(L1,L2),
append(BeforeElement,[E1|AfterElement],L1),
append(BeforeElement,[E2|AfterElement],L2).
其中 BeforeElement 代表元素之前列表的前缀,After Element 代表元素之后列表的后缀。
我得到了一个列表、一个要替换的元素以及该元素的替换项。我设法对该列表中出现的所有元素执行此操作:
replace([],X,Y,[]).
replace([X|T], X, Y, Z) :-
replace(T, X, Y, Z1),
Z = [Y|Z1].
replace([H|T], X, Y, [H|Z]) :-
replace(T, X, Y, Z).
但是现在我必须只替换该元素的第一次出现。 我的思考过程写作:
replace([X|T], X, Y, Z) :-
replace(T, X, Y, Z1),
Z = [Y|Z1].
是:
Z
是 [X|T],X,Y
的结果,如果 Z1
是 T
、XY
和 Z = [Y|Z1]
的结果。按照相同的思考过程,我尝试编写仅替换第一次出现的元素的函数,如下所示:
一个只实现第一次出现的想法是从 replace/4
进入 replace/5
,如果我更换或不这样,我会计算:
replace_single(L,X,Y,Z) :-
replace2(L,X,Y,0,Z).
replace2([],X,Y,C,[]).
replace2([X|T], X, Y, C, Z) :-
\+ (C = 0),
replace2(T, X, Y, C, Z1),
Z = [X|Z1],
C is 1.
replace2([H|T], X, Y, C, [H|Z]) :-
replace2(T, X, Y, C, Z).
显然不行,我有点迷茫。有人可以告诉我如何解决问题或解决方案本身吗?
我们根据same_length/2
、append/3
, maplist/2
, and prolog-dif:
replace/4
replace(Xs,X,Y,Ys) :-
same_length(Xs,Ys),
append(Prefix,[X|Suffix],Xs),
maplist(dif(X),Prefix),
append(Prefix,[Y|Suffix],Ys).
示例查询:
?- replace(Xs,2,two,[1,two,3,4,5,1,2,3,4,5,1,2]).
Xs = [1,2,3,4,5,1,2,3,4,5,1,2]
; false.
?- replace([1,2,3,4,5,1,2,3,4,5,1,2],2,two,Ys).
Ys = [1,two,3,4,5,1,2,3,4,5,1,2]
; false.
另一种方法是使用 DCG:
rep1(X, Y, [Z|T]) --> [Z], { dif(Z, X) }, rep1(X, Y, T).
rep1(X, Y, [Y|T]) --> [X], rest(T).
rep1(_, _, []) --> [].
rest([]) --> [].
rest([H|T]) --> [H], rest(T).
| ?- phrase(rep1(a, 1, L), [a,b,c,a,d]).
L = [1,b,c,a,d] ? ;
| ?- phrase(rep1(a, 1, [x, y, 1, b]), L).
L = [x,y,1,b] ? a
L = [x,y,a,b]
您可以将谓词写成:
replace(X, Y, L, R) :- phrase(rep1(X, Y, R), L).
另一种方法是:-
replace(E1,L1,E2,L2) :-
same_length(L1,L2),
append(BeforeElement,[E1|AfterElement],L1),
append(BeforeElement,[E2|AfterElement],L2).
其中 BeforeElement 代表元素之前列表的前缀,After Element 代表元素之后列表的后缀。