'Filter a list in Prolog
I'm developing an application written in Prolog. I get to a point in which I want to filter a list of elements and remove those which do not meet a certain constraints or conditions, keeping the original list order. I thought the best way for doing it would be something like this:
filter([],Filtered).
filter([L|List],[F|Filtered]) :-
/* Conditions are met: bypass the element to the filtered list */
check_conditions(L),
filter(List,Filtered).
filter([L|List],Filtered) :-
/* Conditions are not met: do not include the element in the filtered list */
filter_aborts(List,Filtered).
Before accepting it as a solution to my problem I wanted to give it a try (independently), so I compiled and run my code (SWI-Prolog) and tested a few situations. When I type in the Prolog query using a hard-coded list (or whatever you want to call it) I get what something like this:
?- filter([id01,id02,id03,id04,id05,id06],F).
F = [id03, id05, id06|_G1024] .
The list is certainly filtered but I get this instance name "_G1024" at the end of it. I understand this happens because F is not instantiated, but I don't know what would be the solution. Moreover, if I try to do something different like entering the list as an instantiated variable, what I get is even more strange:
?- L=[id02,id03,id04,id05,id06].
L = [id02, id03, id04, id05, id06].
?- filter(L,F).
L = [] ;
L = [id01],
F = [id01|_G347] ;
L = [id01, id01],
F = [id01, id01|_G403]
... and so on.
Aren't Prolog variables supposed to be assign-once variables? Does my program actually change L or I am not understanding it correctly? A part from that, since I am new to Prolog, I would appreciate any comment regarding my Prolog -let's say...- "style".
Solution 1:[1]
You use SWI-Prolog, so you can write a predicate which succeeds or fails according to your conditions, then use include(Predidate, Lst, Success) . For axample
include(check_conditions,Lst, Success)
Solution 2:[2]
Also it is possible to filter by index of array:
filterArrByCubeIndexes([],[],_).
filterArrByCubeIndexes([_],[],SI):- isNotCube(SI).
filterArrByCubeIndexes([A],[A],SI):- isNotCube(SI).
filterArrByCubeIndexes([_|T], L, SI):- isNotCube(SI), R1 is SI+1, filterArrByCubeIndexes(T, L, R1).
filterArrByCubeIndexes([X|T], [X|L], SI):- R1 is SI+1, filterArrByCubeIndexes(T, L, R1).
isNotCube(X) :- X=\=round(X**(1/3))*round(X**(1/3))*round(X**(1/3)).
filterArrByCubeIndexes([1,1,3,4,5,6,7,8,9],Z, 1) will produce Z = [1,8]
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | joel76 |
| Solution 2 | Sergey |
