I have some SWI-Prolog dictionary of following form:
dict_label{-N: a(-N), -N+1: a(-N+1), ..., -1: a(-1), 1: a(1), ..., M: a(M)}.
whereby:
a(j), -N≤j≤M
are the values of the dictionary with keys in the integer interval [-N, M]\{0}.
My aim now is to convert this dictionary into some dictionary of form:
dict_label{1: a(1), ..., M: a(M), M+1: a(-N), ..., M+N: a(-1) }.
as example:
P = test_label{-5: e, -4: f, -3: g, -2: h, -1: i, 1: a, 2:b, 3: c, 4: d}
should be converted into:
Q = test_label{1: a, 2: b, 3: c, 4: d, 5: e, 6: f, 7: g, 8: h, 9: i}
I hope you can help me to find some good way to solve the problem and find some predicate to switch negative index in that form.
The problem seems very specific, so I will share an ad-hoc solution to solve it.
The solution requires the transformation of the dict into a list of ordered pairs to work on the keys of such pairs.
The positive keys will remain unchanged while the negative keys will be modified: by using the fact that the list of keys is ordered this can be done by keeping a counter starting at M+1
and gradually updating the list of keys.
Finally the keys are put together with the original values and the list of pairs is transformed again into a dictionary.
This is the code:
dict_normalize(DictIn, DictOut) :-
dict_pairs(DictIn, Tag, Pairs), % transform dict into ordered list of pairs
pairs_normalize(Pairs, NewPairs), % work on the pairs to get the new dict
dict_pairs(DictOut, Tag, NewPairs).
pairs_normalize(PairsIn, PairsOut) :-
pairs_values(PairsIn, Values), % extract values
pairs_keys(PairsIn, Keys), % extract keys
keys_normalize(Keys, NewKeys), % work on the keys to get the new list of pairs
pairs_keys_values(PairsOut, NewKeys, Values).
keys_normalize(KeysIn, KeysOut) :-
max_list(KeysIn, Max),
Start is Max + 1, % determine the starting index for negative values
keys_normalize(KeysIn, Start, KeysOut). % this predicate works because keys are known to be ordered
keys_normalize([], _, []).
keys_normalize([H|T], N, [N|NewT]) :- % negative key
H < 0,
!,
NewN is N + 1,
keys_normalize(T, NewN, NewT).
keys_normalize([H|T], N, [H|NewT]) :- % positive key (unchanged)
keys_normalize(T, N, NewT).
Example:
?- P = test_label{-5: e, -4: f, -3: g, -2: h, -1: i, 1: a, 2:b, 3: c, 4: d},
dict_normalize(P, Q).
P = test_label{-5:e, -4:f, -3:g, -2:h, -1:i, 1:a, 2:b, 3:c, 4:d},
Q = test_label{1:a, 2:b, 3:c, 4:d, 5:e, 6:f, 7:g, 8:h, 9:i}.