Самым простым решением было бы преобразовать это в список, отфильтровать список с помощью предиката, а затем создать новый assoc.
:- use_module(library(assoc)).
:- use_module(library(apply)).
filter_assoc_l(Filter, In, Out) :-
assoc_to_list(In, List),
include(Filter, List, OutList),
list_to_assoc(OutList, Out).
Вы, видимо, не можете этого сделать. Но вам по-прежнему нужен способ повторения всех элементов assoc без входа в цикл, основанный на сбоях, который будет отменять ваши привязки после каждого сбоя. gen_assoc
даст вам все ключи, но вам придется либо использовать findall/3
(что делает его таким же, как преобразование в список), либо вам придется терпеть неудачу после каждой привязки (отменяя вашу работу).
Другой подход заключается в том, чтобы получить список только ключей, а затем использовать предикат удаления, чтобы избавиться от значений, не соответствующих фильтру. Сначала нам нужно получить ключи, а затем вызвать вспомогательный предикат для просмотра списка ключей:
filter_assoc_unlist(Filter, In, Out) :-
assoc_to_keys(In, Keys),
filter_assoc_keys(Filter, In, Keys, Out).
Теперь мы можем получить текущий ключ/значение (заголовок списка ключей), а затем вызвать предикат вашего фильтра, чтобы проверить его. Если он проходит, мы просто повторяемся; если это не удается, мы удаляем его и передаем результат удаления на рекурсивный шаг.
filter_assoc_keys(Filter, In, [Key|Keys], Out) :-
min_assoc(In, Key, Value),
(call(Filter, Key-Value) ->
filter_assoc_keys(Filter, In, Keys, Out)
;
del_assoc(Key, In, _, Next),
filter_assoc_keys(Filter, Next, Keys, Out)
).
Когда у нас заканчиваются ключи, вход становится выходом:
filter_assoc_keys(_, Out, [], Out).
Я не знаю, соответствует ли это вашим критериям или нет, но я надеюсь, что это так.
person
Daniel Lyons
schedule
26.11.2019
Wynik
? - person Daniel Lyons   schedule 26.11.2019