csv - 使用 Prolog 将 csv 文件中的数据解析为给定格式
问题描述
我的 csv 文件包含以下数据:
A B C
A - 4 5
B 8 - 6
C 2 3 -
我想要以下形式的事实:
num(a,b,4).
num(a,c,5).
num(b,a,8).
num(b,c,6).
num(c,a,2).
num(c,b,3).
类似的字母不应该有事实,比如 num(a,a,-)。
我正在使用 prolog 的 csv_read_file 作为:
csv_read_file(Path, Rows, [functor(num), arity(4)]), maplist(assert, Rows).
它给我的输出为:
Rows = [num('', 'A', 'B', 'C'), num('A', -, 4, 5), num('B', 8, -, 6), num('C', 2, 3, -)]
这似乎是一个基本问题,但我无法考虑执行此操作的条件。任何帮助将不胜感激。
根据伊莎贝尔新手的回答:
Open :- csv_read_file('Path', Rows, [functor(num), arity(4)]), table_entry(Rows, Row).
header_row_entry(Header,Row,Entry):-
arg(1, Row, RowName),
functor(Header, _, Arity),
between(2,Arity,ArgIndex),
arg(ArgIndex, Header, ColumnName),
arg(ArgIndex, Row, Value),
Entry = num(RowName, ColumnName, Value),
writeln(Entry).
table_entry(Entries, Entry):-
Entries = [Header | Rows],
member(Row, Rows),
header_row_entry(Header, Row, Entry).
现在,任何人都可以解释我应该如何以及在何处使用 maplist 以事实形式转换行(暂时忽略“-”和小写的过滤),以便在查询时:
?-num(A,B,X).
我应该得到:
X=4
下一个任务是,我想在它上面实现深度优先搜索算法。任何有关此的细节将不胜感激。
解决方案
考虑一个表头num('', 'A', 'B', 'C')
和表中的一行num('B', 8, -, 6)
。由此,您要计算由行名(此处为'B'
)和列名标识的表条目:列名'A'
用于第一个值(8
),'B'
第二个值( ) -
,'C'
第三个值(6
)。
这是一种简单的方法,涉及一些打字和强制性的复制和粘贴错误:
header_row_entry(Header, Row, Entry) :-
Header = num('', ColumnName, _, _),
Row = num(RowName, Value, _, _),
Entry = num(RowName, ColumnName, Value).
header_row_entry(Header, Row, Entry) :-
Header = num('', _, ColumnName, _),
Row = num(RowName, _, Value, _),
Entry = num(RowName, ColumnName, Value).
header_row_entry(Header, Row, Entry) :-
Header = num('', _, _, ColumnName),
Row = num(RowName, _, _, Value),
Entry = num(RowName, ColumnName, Value).
这将枚举回溯行中的所有条目:
?- Header = num('', 'A', 'B', 'C'), Row = num('B', 8, -, 6),
header_row_entry(Header, Row, Entry).
Header = num('', 'A', 'B', 'C'),
Row = num('B', 8, -, 6),
Entry = num('B', 'A', 8) ;
Header = num('', 'A', 'B', 'C'),
Row = num('B', 8, -, 6),
Entry = num('B', 'B', -) ;
Header = num('', 'A', 'B', 'C'),
Row = num('B', 8, -, 6),
Entry = num('B', 'C', 6).
要枚举整个表中的所有条目,仍然需要枚举所有行,然后如上所述枚举行条目。这是:
table_entry(Entries, Entry) :-
Entries = [Header | Rows],
member(Row, Rows),
header_row_entry(Header, Row, Entry).
现在,给定你的桌子:
?- Table = [num('', 'A', 'B', 'C'), num('A', -, 4, 5), num('B', 8, -, 6), num('C', 2, 3, -)], table_entry(Table, Entry).
Table = [num('', 'A', 'B', 'C'), num('A', -, 4, 5), num('B', 8, -, 6), num('C', 2, 3, -)],
Entry = num('A', 'A', -) ;
Table = [num('', 'A', 'B', 'C'), num('A', -, 4, 5), num('B', 8, -, 6), num('C', 2, 3, -)],
Entry = num('A', 'B', 4) ;
Table = [num('', 'A', 'B', 'C'), num('A', -, 4, 5), num('B', 8, -, 6), num('C', 2, 3, -)],
Entry = num('A', 'C', 5) ;
Table = [num('', 'A', 'B', 'C'), num('A', -, 4, 5), num('B', 8, -, 6), num('C', 2, 3, -)],
Entry = num('B', 'A', 8) ;
Table = [num('', 'A', 'B', 'C'), num('A', -, 4, 5), num('B', 8, -, 6), num('C', 2, 3, -)],
Entry = num('B', 'B', -) . % etc.
根据您确切想要的内容,它仍然将行名和列名小写(downcase_atom
例如,在 SWI-Prolog 中令人讨厌的名称)并过滤掉-
条目。然后,您可以使用失败驱动的循环或通过使用收集所有条目并使用 断言来断言findall
条目maplist
。
现在我们有了一个可行的解决方案,我们可能想要header_row_entry
更好一点。我们可以使用arg/3
更明确地捕获我们正在尝试将列名和值配对,这些列名和值在它们各自的标题和行术语中位于相同的参数位置:
header_row_entry(Header, Row, Entry) :-
arg(1, Row, RowName),
functor(Header, _, Arity),
between(2, Arity, ArgIndex),
arg(ArgIndex, Header, ColumnName),
arg(ArgIndex, Row, Value),
Entry = num(RowName, ColumnName, Value).
这比上面的要短,适用于表中的任意数量的列。
推荐阅读
- filesystems - ext4 文件系统如何将目录条目结构从线性更改为 Htree?
- docker - from builtins import bytes # pylint: disable=redefined-builtin ImportError: No module named builtins
- javascript - 数据库中复选框中的“打印”值
- matlab - 特定范围内的曲线循环伏安法下面积
- android - 在哪里/如何存储敏感信息?
- jquery - 在django中用jquery实时更新模板可以吗?
- c# - 以编程方式创建测试
- amazon-web-services - 使用 aws Autoscaling 组直接附加应用程序负载均衡器/网络负载均衡器
- cookies - Cookies不会一直删除角度7
- android - 有没有办法导航到目的地并将另一个添加到 NavigationManager 中的 backtstack?