为多个表调整 csv 读取
Adapting csv reading for multiple tables
我有以下内容:
:- use_module(library(csv)).
:- dynamic mb/3.
:- dynamic mb_column_keys/1.
prepare_db(File) :-
retractall(mb_column_keys(_)),
retractall(mb(_,_,_)),
forall(read_row(File, Row), store_row(Row)).
store_row(Row) :-
Row =.. [row|Cols],
( mb_column_keys(ColKeys)
-> Cols = [RowKey|Samples],
maplist(store_sample(RowKey), ColKeys, Samples)
; (Cols = [_H|T],assertz(mb_column_keys(T)))
).
store_sample(RowKey, ColKey, Sample) :-
assertz(mb(RowKey, ColKey, Sample)).
read_row(File, Row) :-
csv_read_file_row(File, Row, []),
writeln(read_row(Row)).
最好的调整方法是什么,以便 prepare_db 可以使用两个额外的参数来定义 column_keys 和 mb 的谓词。
例如?-prepare_db('my_file.csv',mb_column_keys,mb).
会导致 mb/3 和 mb_column_keys/1
的事实被断言
好的,我已将文件更改为以下有效的文件:
:- use_module(library(csv)).
:- set_prolog_stack(global, limit(4*10**9)).
prepare_db(File, Column_Key,Relation) :-
Column_Key_Term =.. [Column_Key,_],
Relation_Term =.. [Relation,_,_,_],
retractall(Column_Key_Term),
retractall(Relation_Term),
forall(read_row(File, Row), store_row(Row,Column_Key,Relation)).
store_row(Row,Column_Key,Relation) :-
Column_Key_Test =.. [Column_Key,ColKeys],
Row =.. [row|Cols],
( call(Column_Key_Test)
-> Cols = [RowKey|Values],
maplist(store_relation(Relation,RowKey), ColKeys, Values)
; ( Cols = [_H|T],
Column_Key_Term =.. [Column_Key,T],
assertz(Column_Key_Term)
)
).
store_relation(Relation,RowKey, ColKey, Values) :-
Relation_Term =.. [Relation,RowKey,ColKey,Values],
assertz(Relation_Term).
read_row(File, Row) :-
csv_read_file_row(File, Row, []),
writeln(read_row(Row)).
但是看起来有点难看,有没有更优雅的方式来实现呢?
由于 retractall/1
将其参数声明为 dynamic
,您可以将谓词 Heads 列表传递给 prepare_db
,如下所示:
prepare_db(File, Heads) :-
maplist(retractall, Heads),
% etc
?- prepare_db('my_file.csv', [mb_column_keys(_) ,mb(_,_,_)]).
请记住,SWI-Prolog 至少允许您调用 dynamic/1
:
?- foo(_).
ERROR: toplevel: Undefined procedure: foo/1 (DWIM could not correct goal)
?- dynamic(foo/1).
true.
?- foo(_).
false.
(如果您在 retractall/1
文档的脚注行之间阅读,您会发现这是可能的...)
正如你在问题下的错误评论,声明动态谓词仍然很好的原因是有原因的。
我有以下内容:
:- use_module(library(csv)).
:- dynamic mb/3.
:- dynamic mb_column_keys/1.
prepare_db(File) :-
retractall(mb_column_keys(_)),
retractall(mb(_,_,_)),
forall(read_row(File, Row), store_row(Row)).
store_row(Row) :-
Row =.. [row|Cols],
( mb_column_keys(ColKeys)
-> Cols = [RowKey|Samples],
maplist(store_sample(RowKey), ColKeys, Samples)
; (Cols = [_H|T],assertz(mb_column_keys(T)))
).
store_sample(RowKey, ColKey, Sample) :-
assertz(mb(RowKey, ColKey, Sample)).
read_row(File, Row) :-
csv_read_file_row(File, Row, []),
writeln(read_row(Row)).
最好的调整方法是什么,以便 prepare_db 可以使用两个额外的参数来定义 column_keys 和 mb 的谓词。
例如?-prepare_db('my_file.csv',mb_column_keys,mb).
会导致 mb/3 和 mb_column_keys/1
的事实被断言好的,我已将文件更改为以下有效的文件:
:- use_module(library(csv)).
:- set_prolog_stack(global, limit(4*10**9)).
prepare_db(File, Column_Key,Relation) :-
Column_Key_Term =.. [Column_Key,_],
Relation_Term =.. [Relation,_,_,_],
retractall(Column_Key_Term),
retractall(Relation_Term),
forall(read_row(File, Row), store_row(Row,Column_Key,Relation)).
store_row(Row,Column_Key,Relation) :-
Column_Key_Test =.. [Column_Key,ColKeys],
Row =.. [row|Cols],
( call(Column_Key_Test)
-> Cols = [RowKey|Values],
maplist(store_relation(Relation,RowKey), ColKeys, Values)
; ( Cols = [_H|T],
Column_Key_Term =.. [Column_Key,T],
assertz(Column_Key_Term)
)
).
store_relation(Relation,RowKey, ColKey, Values) :-
Relation_Term =.. [Relation,RowKey,ColKey,Values],
assertz(Relation_Term).
read_row(File, Row) :-
csv_read_file_row(File, Row, []),
writeln(read_row(Row)).
但是看起来有点难看,有没有更优雅的方式来实现呢?
由于 retractall/1
将其参数声明为 dynamic
,您可以将谓词 Heads 列表传递给 prepare_db
,如下所示:
prepare_db(File, Heads) :-
maplist(retractall, Heads),
% etc
?- prepare_db('my_file.csv', [mb_column_keys(_) ,mb(_,_,_)]).
请记住,SWI-Prolog 至少允许您调用 dynamic/1
:
?- foo(_).
ERROR: toplevel: Undefined procedure: foo/1 (DWIM could not correct goal)
?- dynamic(foo/1).
true.
?- foo(_).
false.
(如果您在 retractall/1
文档的脚注行之间阅读,您会发现这是可能的...)
正如你在问题下的错误评论,声明动态谓词仍然很好的原因是有原因的。