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.
CodePudding user response:
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}.