将元组事实过滤到新列表

Filter tuple facts to new list

我在尝试过滤通过 CSV 导入的事实时遇到问题。我有以下 CSV 文件:

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

这是使用 csv_read_file 函数导入到我的文件中的。例如,我可以然后 运行 check 查看 CSV 中是否导入了包含字母 'e' 和 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).

我现在想做的是减少通过 CSV 导入的包含 'e' 的事实子集,并将它们存储在另一种数据类型中以备后用。这不起作用,但我想做的是像 check('e') 那样过滤所有事实,但将结果存储在 Output.

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

我可以全部打印出来,是否可以将其存储在列表中?

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

也试过这个

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

谢谢

您使用 findall/3 将输出收集到列表中是正确的。不过,请查看 documentation 的 findall。

如果您想从 fact/4 中收集所有匹配的 S,您可以使用:

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

如果你想收集全部事实,它会是这样的:

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

请注意 sub_string/5 回溯,因此它可能会为每个字符串多次匹配子字符串。