How do you do a search and replace of a list with another sublist in Prolog?
Asked Answered
H

2

5

I'm trying to modify a list by search and replace, was wondering how do I search through a list with the search term as a list as well?

Lets say I have a list [1,2,3,4] I want to single out the 2 and 3 and replace it with 5,6 so ideally I could have a predicate:

search_and_replace(Search_Term, Replace_Term, Target_List, Result_List).

eg.

search_and_replace([2,3], [5,6], [1,2,3,4], Result_List), write(Result_List).
Houphouetboigny answered 29/11, 2011 at 14:33 Comment(0)
C
4

You can use append/2 as follows :

replace(ToReplace, ToInsert, List, Result) :-
    once(append([Left, ToReplace, Right], List)),
    append([Left, ToInsert, Right], Result).

With or without use of once/1 depending on if you want all the possibilies or not.

To replace all the occurences I'd go with something like :

replace(ToReplace, ToInsert, List, Result) :-
    replace(ToReplace, ToInsert, List, [], Result).
replace(ToReplace, ToInsert, List, Acc, Result) :-
    append([Left, ToReplace, Right], List),
    append([Acc, Left, ToInsert], NewAcc),
    !,
    replace(ToReplace, ToInsert, Right, NewAcc, Result).
replace(_ToReplace, _ToInsert, [], Acc, Acc).
Commonweal answered 29/11, 2011 at 14:48 Comment(1)
Hmm.. I noticed that the predicate only searches and replace one, how do you apply to all terms globally?Houphouetboigny
B
6

Let me assume that you want to replace a subsequence substring within a list by another list.

Here is a general way how to do this. You might want to insert further conditions into the program.

replacement(A, B,  Ag, Bg) :-
   phrase((seq(S1),seq(A),seq(S2)), Ag),
   phrase((seq(S1),seq(B),seq(S2)), Bg).

seq([]) --> [].
seq([E|Es]) --> [E], seq(Es).

And, yes this can be optimized a bit - even its termination property would profit. But conceptual clarity is a quite precious value...

Edit: Your example query:

?- replacement([2,3], [5,6], [1,2,3,4], Xs).
   Xs = [1,5,6,4]
;  false.
Beveridge answered 29/11, 2011 at 14:44 Comment(1)
Very nice, DCG is pretty new to me but it seems like an elegant solution.Houphouetboigny
C
4

You can use append/2 as follows :

replace(ToReplace, ToInsert, List, Result) :-
    once(append([Left, ToReplace, Right], List)),
    append([Left, ToInsert, Right], Result).

With or without use of once/1 depending on if you want all the possibilies or not.

To replace all the occurences I'd go with something like :

replace(ToReplace, ToInsert, List, Result) :-
    replace(ToReplace, ToInsert, List, [], Result).
replace(ToReplace, ToInsert, List, Acc, Result) :-
    append([Left, ToReplace, Right], List),
    append([Acc, Left, ToInsert], NewAcc),
    !,
    replace(ToReplace, ToInsert, Right, NewAcc, Result).
replace(_ToReplace, _ToInsert, [], Acc, Acc).
Commonweal answered 29/11, 2011 at 14:48 Comment(1)
Hmm.. I noticed that the predicate only searches and replace one, how do you apply to all terms globally?Houphouetboigny

© 2022 - 2024 — McMap. All rights reserved.