Search code examples
prologswi-prolog

Filter tuple facts to new list


I'm having an issue with trying to filter facts imported through a CSV. I have the following CSV file:

"colA","colB","colC","colD"
"what","is","the","chocolate"
"hello","my","friend","person"
"time","for","some","food"
"when","is","my","event"

This is imported in my file using csv_read_file function. As an example I'm able to then run check to see if there is a fact with a third word imported in the CSV that contains the letter 'e' with check('e').

:- use_module(library(csv)).

import :-
    csv_read_file('./data.csv', Data, [functor(fact)]),
    maplist(assert, Data).

check(Q) :-
        fact(_,_,S,_),
        sub_string(S,_,_,_,Q).

What i'm trying to do now is reduce the subset of facts imported through the CSV that contain 'e', and store those in another data type to use later on. This isn't working but what I'm trying to do is filter all facts like in check('e') but store the results in Output.

filter(Q, Output) :-
        findall(
                fact(_,_,S,_),
                sub_string(S,_,_,_,Q),
                Output
        ).

I can print all out, is it possible to store this in a list?

forall((fact(A,B,S,D), sub_string(S,_,_,_,'e')), print(S)).

Also tried with this

include(sub_string(S,_,_,_,'e'), fact(A,B,S,D), R).

Thanks


Solution

  • You were right using findall/3 to collect your output onto a list. Check out the documentation for findall though.

    If you want to collect all matching S from fact/4 you may use:

    filter(Q, Output) :-
        findall(S,
                ( fact(_, _, S, _),
                  sub_string(S, _, _, _, Q)
                ),
                Output).
    

    and if you want to gather the whole fact it would be something like this:

    filter(Q, Output) :-
        findall(fact(A, B, S, C),
                ( fact(A, B, S, C),
                  sub_string(S, _, _, _, Q)
                ),
                Output).
    

    Note that sub_string/5 backtracks so it may match the substring more than once for each string.