Prolog读取文件并将数据用作不同功能的输入

Prolog read file and use the data as input for different functions

我想从文件中读取,然后以列表的形式存储。每出现一个逗号,它就会将逗号前的所有字符组合成一个新词。一个新行将表明它是一个新的子列表。这与 java 在读取文件时可以做的非常相似。我正在学习序言并且在读取文件并将它们作为输入以执行不同操作时遇到问题。你知道有什么方法可以帮助我读取文件并将这些数据用作不同功能的输入吗?谢谢。

读取文件:

泰雷兹、奥利维亚、杰克逊、索菲亚

加拿大Post、索菲亚、杰克逊、奥利维亚

思科、奥利维亚、索菲亚、杰克逊

代码:

read_from_file(File, A):-
   open(File, read, Stream),
   get_char(Stream, Char1),
   process_the_stream(Char1, Stream, A),
   close(Stream).

write_on_file(File,Text):-
   open(File, append, Stream),
   write(Stream, Text), nl,
   close(Stream).

process_the_stream(end_of_file, _, []):- !.

process_the_stream(Char, Stream, [Char|B]):-
   write(Char),
   get_char(Stream, Char2),
   process_the_stream(Char2, Stream, B).

当前输出:

A = ['T',h,a,l,e,s,',','O',l,i,v,i,a,',','J',a,c,k,s,o,n,',','S',o,p,h,i,a,'\n','C',a,n ,a,d,a,' ','P',o,s,t,',','S',o,p,h,i,a,',','J',a,c,k,s,o,n,',','O',l,i,v,i,a,'\n','C',i,s,c ,o,',','O',l,i,v,i,a,',','S',o,p,h,i,a,',','J',a,c,k,s,o,n]

期望输出:

A = [[泰雷兹、奥利维亚、杰克逊、索菲亚]、[加拿大 Post、索菲亚、杰克逊、奥利维亚]、[思科、奥利维亚、索菲亚、杰克逊]]

这使用 SWI-Prolog 8.x.y

:- use_module(library(csv)).

process_csv(File,Values) :-
    csv_read_file(File,Rows),
    rows_to_values(Rows,Values).

rows_to_values([],[]).
rows_to_values([Row|Rows],[Values|Values0]) :-
    row_to_values(Row,Values),
    rows_to_values(Rows,Values0).

row_to_values(Row,Values) :-
    Row =.. List,
    List = [_Functor|Values].

示例运行

?- process_csv('C:/Users/Groot/Documents/Projects/Prolog/SO_question_189_data.txt',Values).
Values = [['Thales', 'Olivia', 'Jackson', 'Sophia'], ['Canada Post', 'Sophia', 'Jackson', 'Olivia'], ['Cisco', 'Olivia', 'Sophia', 'Jackson']].

这个答案与您想要的答案不同的原因是原子以 ' 结尾,因此它们是原子而不是变量,因为变量以大写字母开头。

如果你喜欢更简单的东西,那么

:- use_module(library(csv)).

process_csv(File,Values) :-
    csv_read_file(File,Rows),
    maplist(row_to_values,Rows,Values).

row_to_values(Row,Values) :-
    Row =.. [_Functor|Values].

使用 Logtalk 的简单便携式解决方案,您可以在大多数 Prolog 系统中运行:


:- object(process).

    :- public(data/2).
    data(File, Data) :-
        open(File, read, Stream),
        reader::line_to_codes(Stream, Line),
        process_data(Line, Stream, Data),
        close(Stream).

    process_data(end_of_file, _, []).
    process_data([Code| Codes], Stream, [Names| Data]) :-
        atom_codes(Atom, [Code| Codes]),
        atom::split(Atom, ',', Names),
        reader::line_to_codes(Stream, Line),
        process_data(Line, Stream, Data).

:- end_object.

示例调用,假设数据文件没有空行且名称之间没有空格,如问题示例数据文件内容:

| ?- {types(loader), reader(loader), process}.
...
yes

| ?- process::data('data.txt', Names).
Names = [['Thales', 'Olivia', 'Jackson', 'Sophia'], ['Canada Post', 'Sophia', 'Jackson', 'Olivia'], ['Cisco', 'Olivia', 'Sophia', 'Jackson']]
yes