Пролог таблицы сопоставления фильтров

Мне нужно написать предикат include_assoc/3, который фильтрует ассоциативный массив (второй аргумент) с заданным предикатом (первый аргумент) и записывает результат в третий аргумент. Предикат должен работать аналогично включению / 3. Предикат фильтра должен использовать пару ключ-значение в качестве аргумента.

Я не могу преобразовать таблицу в список перед фильтрацией. Как мне это сделать?

Мой код

include_assoc(_,X,_):-
    empty_assoc(X),!.
include_assoc(Filtr,Tab,Result):-
    min_assoc(Tab,Key,Value),
    del_min_assoc(Tab,_,_,Tab1),
    (call(Filtr,Key-Value) -> 
    (include_assoc(Filtr,Tab1,Result1),
    put_assoc(Key,Result1,Value,Result));
    include_assoc(Filtr,Tab1,Result1)).

person restarcik    schedule 26.11.2019    source источник
comment
Пожалуйста, поделитесь с нами своей попыткой, и мы поможем вам выйти из тупика.   -  person Daniel Lyons    schedule 26.11.2019
comment
@Daniel Lyons я вставил код   -  person restarcik    schedule 26.11.2019
comment
Что такое Wynik?   -  person Daniel Lyons    schedule 26.11.2019
comment
@DanielLyons О, извините, у меня были другие имена переменных в моем исходном коде, но теперь я внес некоторые изменения и похоже, что это работает   -  person restarcik    schedule 26.11.2019


Ответы (1)


Самым простым решением было бы преобразовать это в список, отфильтровать список с помощью предиката, а затем создать новый 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