Подтвердить что ты не робот

Пролог: Фильтрация списка?

В настоящее время я работаю над очень коротким проектом Prolog и просто застрял, пытаясь применить "фильтр", который я создал в списке. У меня есть то, что вы могли бы назвать фильтром готовым, но я не могу его применить. Было бы лучше проиллюстрировать:

filter(A, B) 

... выводит "true", если выполняются определенные условия.

filterList(A, [X, Y, Z])

... выводит список, содержащий все элементы из второго аргумента, которые делают выходной фильтр false. (Таким образом, если фильтр (A, X) истинен, выходной сигнал [Y, Z]).

У меня есть функция "фильтр", но теперь мне нужно применить ее к списку, как показано на втором примере, за исключением всех элементов, для которых фильтр возвращает true при применении с первым аргументом.

Итак, если фильтр является простым A == B, функция должна получать A [A, B, A, C, D, A] и выводить [B, C, D], удалив все элементы, для которых фильтр применяется, очевидно.

У меня возникают проблемы с базовой структурой функции, поэтому, если кто-то может предоставить базовый план для такой функции, как это, это будет очень полезно. Я упростил ситуацию настолько, насколько это возможно, поэтому я могу взять все, что вы можете предоставить и изменить для моих нужд.

Спасибо заранее!

4b9b3361

Ответ 1

Если вы ищете функции более высокого порядка в Прологе, вам обязательно следует обратиться к Naish (1995), очень хорошему источнику по этому вопросу.

Его определение filter/3 следующее (он использует нотацию списка различий, поэтому избегает необходимости определять filter/4):


filter(_,[],[]).
filter(P, A0-As0, As) :-
    (
        call(P, A0) -> As = A0-As1
    ;
        As = As1
    )
    , filter(P, As0, As1).

Если у вас есть вопросы по этому предикату, пожалуйста, спросите меня в комментарии. Чтение бумаги также настоятельно рекомендуется, это также бросает вызов map, foldr и compose ! Следует отметить, что многие из ограничений, которые он упоминает (как, например, отсутствует call/3 или более высокого порядка, apply не применяются больше. SWI-Prolog имеет =.. оператор, который адресует все его проблемы и делает произвольную N- Логика заказа возможна.

Ответ 2

SWI-Prolog предлагает exclude/3 и другие подобные мета-предикаты. Ваша исходная проблема может быть закодирована следующим образом:

are_identical(X, Y) :-
    X == Y.

filterList(A, In, Out) :-
    exclude(are_identical(A), In, Out).

Пример использования:

?- filterList(A, [A, B, A, C, D, A], Out).
Out = [B, C, D].

Ответ 3

Существует неотъемлемая проблема с функциями фильтра, которые используют успех или неудачу предиката в качестве критерия фильтрации: результирующая программа больше не является чистой монотонной программой. Поэтому он теряет все свои декларативные свойства; единственное значение, которое остается, является процедурной поэтапной интерпретацией. Вот чистая, перезаработанная версия фильтрации с помощью if_/3:

tfilter(_CT_2,    [], []).
tfilter(CT_2, [E|Es], Fs0) :-
   if_(call(CT_2,E), Fs0 = [E|Fs], Fs0 = Fs ),
   tfilter(CT_2, Es, Fs).

Таким образом, первым аргументом является замыкание/продолжение, которое получит еще два аргумента: Элемент и результирующее значение истины.

=(X,X,true).
=(X,Y,false) :- dif(X,Y).

Теперь результаты остаются точными:

| ?- tfilter(=(X),[A,B],Xs).
B = A,
X = A,
Xs = [A,A] ? ;
X = A,
Xs = [A],
dif(A,B) ? ;
X = B,
Xs = [B],
dif(B,A) ? ;
Xs = [],
dif(X,A),
dif(X,B) ? ;
no

Существует четыре возможности, по которым можно фильтровать список из двух элементов по критерию равным X. Каждый элемент может быть равен или может отличаться.

Недостатком этого подхода является то, что нужно предоставить обновленные версии всех критериев.

Ответ 4

Хорошо, что ты знаешь, я просто понял это. Итак, здесь я отправляю ответ на свой вопрос, как и ожидалось, действительно короткая функция выполняла работу:

filterList(_,[],R,R).           % Returns answer when the list is exhausted.
filterList(L,[A|List],Temp,Res) :-
   filterList(L,List,New,Res),  % Recursive call, New is either the same list
   (  filter(L,A),              % in case the filter outputs true, or the list
      New = Temp
   ;  New = [A|Temp]            % plus the current element otherwise.
   ).

Ответ 5

Я получаю взрослых в стране //Obtengo los adultos de un pais, Страна = Pais, People = Personas, Person = una sola Persona

habitants(USA, [juan, pedro, david])

adults(Adults, Country) :-
     findall(Person, (habitants(Country,People), member(People, Person), adult(Person)), Adults)

Это фильтр в прологе //Asi es un filter en prolog

Ответ 6

filter(_,[],[]).
filter(Predicate,[First|Rest],[First|Tail]) :-
   filter(Predicate,Rest,Tail).
filter(Predicate,[_|Rest],Result) :-
   filter(Predicate,Rest,Result).