Есть ли способ сделать это?
Конечно. И, как говорится в Perl: «Есть несколько способов сделать это».
Пара проблем:
Не используйте (1,b)
. Вместо этого используйте идиоматиз c -(1,b)
, который записывается как 1-b
(пара). Это дает вам список пар: L=[1-b,3-m]
. Есть библиотека, специально работающая с такими парами: https://www.swi-prolog.org/pldoc/man?section=pairs - в качестве альтернативы вы можете использовать реальные карты, реализованные с помощью деревьев AVL: https://www.swi-prolog.org/pldoc/man?section=assoc
Теперь вам просто нужно
- отсортировать список пар, возможно, используя сортировку ключей: https://www.swi-prolog.org/pldoc/doc_for?object=sort / 2 или https://www.swi-prolog.org/pldoc/doc_for?object=sort / 4
- Go по списку слева направо, сохраняя текущий индекс и выполняя замену, когда нажимается следующий ключ в вашем отсортированном списке, или просто сохраняя существующий термин из списка в противном случае. Результат помещается в переменную-накопитель в качестве заголовка списка.
- Готово! Специальная обработка за пределами индексов et c. быть подходящим образом обработанным путем броска или неудачи.
Как go просмотреть отсортированный список пар (я не проверял это!):
% case of Index hit:
go_through([Index-Value|Rest],Index,InList,OutList) :-
InList = [I|Rest],
OutList = [Value|More],
succ(Index,NextIndex),
go_through(Rest,NextIndex,Rest,More).
% case of Index miss:
go_through([NotYetIndex-Value|Rest],Index,InList,OutList) :-
NotYetIndex > Index, % that should be the case
InList = [I|Rest],
OutList = [I|More],
succ(Index,NextIndex),
go_through(Rest,NextIndex,Rest,More).
go_through([],_,L,L). % DONE
В качестве альтернативы вы может написать replace0
, который заменяет по индексу в списке, и go через список L
.
Приложение: рабочий код с использованием go_through
На самом деле содержит несколько тонкостей
another_vectorial_replace1(ListIn,ReplacePairs,ListOut) :-
maplist([_,_]>>true,ListIn,ListOut), % Bonus code: This "makes sure" (i.e. fails if not)
% that ListIn and ListOut are the same length
maplist([(A,B),A-B]>>true,ReplacePairs,RealPairs), % Transform all (1,b) into [1,b]
maplist([K-_]>>integer(K),RealPairs), % Make sure the RealPairs all have integers on first place
keysort(RealPairs,RealPairsSorted), % Sorting by key, which are integers; dups are not removed!
debug(topic,"ListIn: ~q",[ListIn]),
debug(topic,"RealPairsSorted: ~q",[RealPairsSorted]),
go_through(RealPairsSorted,1,ListIn,ListOut),
debug(topic,"ListOut: ~q",[ListOut]).
% Case of Index hit, CurIndex is found in the first "Replacement Pair"
go_through([CurIndex-Value|RestPairs],CurIndex,ListIn,ListOut) :-
!, % Commit to choice
ListIn = [_|Rest],
ListOut = [Value|More],
succ(CurIndex,NextIndex),
go_through(RestPairs,NextIndex,Rest,More).
% Case of Index miss:
go_through([NotYetIndex-V|RestPairs],CurIndex,ListIn,ListOut) :-
NotYetIndex > CurIndex, % that should be the case because of sorting; fail if not
!, % Commit to choice
ListIn = [X|Rest],
ListOut = [X|More],
succ(CurIndex,NextIndex),
go_through([NotYetIndex-V|RestPairs],NextIndex,Rest,More).
% Case of DONE with list traversal
% Only succeed if there are not more pairs left (i.e. no out-of-bound replacements)
go_through([],_CurIndex,L,L).
% ===
% Tests
% ===
:- begin_tests(another_vectorial_replace1).
test(empty) :- another_vectorial_replace1([],[],LO),
LO=[].
test(nop_op) :- another_vectorial_replace1([a,b,c,d],[],LO),
LO=[a,b,c,d].
test(one) :- another_vectorial_replace1([a],[(1,xxx)],LO),
LO=[xxx].
test(two) :- another_vectorial_replace1([a,b,c,d],[(4,y),(2,x)],LO),
LO=[a,x,c,y].
test(full) :- another_vectorial_replace1([a,b,c,d],[(1,e),(2,f),(3,g),(4,h)],LO),
LO=[e,f,g,h].
test(duplicate_replacement,[fail]) :- another_vectorial_replace1([a],[(1,x),(1,y)],_).
test(out_of_bounds_high,[fail]) :- another_vectorial_replace1([a],[(2,y)],_).
test(out_of_bounds_low,[fail]) :- another_vectorial_replace1([a],[(0,y)],_).
:- end_tests(another_vectorial_replace1).
rt :- debug(topic),run_tests(another_vectorial_replace1).
Приложение 2
Замена с использованием maplist/N
, foldl/N
и library(assoc)
За кулисами исчезают рекурсивные вызовы!
https://github.com/dtonhofer/prolog_notes/blob/master/code/vector_replace0.pl