我是Prolog新手。在SWI Prolog中,我试图弄清楚如何可逆地解析一行简单的CSV,但是我卡住了。下面是我得到的结果:
csvstring1(S, L) :-
split_string(S, ',', ',', T),
maplist(atom_number, T, L).
csvstring2(S, L) :-
atomic_list_concat(T, ',', S),
maplist(atom_number, T, L).
% This one is the same except that maplist comes first.
csvstring3(S, L) :-
maplist(atom_number, T, L),
atomic_list_concat(T, ',', S).
现在,csvstring1和csvstring2以“向前”方式工作:
?- csvstring1('1,2,3,4', L).
L = [1, 2, 3, 4].
?- csvstring2('1,2,3,4', L).
L = [1, 2, 3, 4].
但不包括csvstring3:
?- csvstring3('1,2,3,4', L).
ERROR: Arguments are not sufficiently instantiated
此外,csvstring3反向工作,但其他两个 predicate 不是这样:
?- csvstring3(L, [1,2,3,4]).
L = '1,2,3,4'.
?- csvstring1(L, [1,2,3,4]).
ERROR: Arguments are not sufficiently instantiated
?- csvstring2(L, [1,2,3,4]).
ERROR: Arguments are not sufficiently instantiated
我怎样才能把这些组合成一个 predicate 呢?
4条答案
按热度按时间arknldoa1#
我不知道有什么特别适合新手的方法可以做到这一点,而且不会在某个地方妥协。这是最简单的方法:
但是它制造并留下了虚假的选择点,这有点烦人。
这减少了选择点,这是很好的使用时,但穷人的做法进入没有意识到这意味着什么:
这里使用if/else,它的代码更少:
但是logically bad and you should reify the branching with if_不是内置在SWI Prolog中的,使用起来不太简单。
或者你可以用DCG写一个语法,这不是新手的领域:
例如:
但是现在你又回到了原来的样子,在解析 * 和 * 时留下了虚假的选择点,你必须处理SWI Prolog中字符串/原子/字符代码的历史分割;由于双引号标记,该列表将与
"11,22,33,44,55"
统一,但看起来不会。u2nhd7ah2#
split_string是不可逆的。可以使用DCG -下面是一个简单的CSV多行DCG解析器:
为了证明可逆性:
要解析字段内容并保持可逆性,可以使用例如atom_codes。
iklwldmw3#
其他人已经给出了一些建议和大量代码。使用SWI-Prolog,要解析逗号分隔的整数,你可以使用库(dcg/basics)和库(dcg/high_order)来做这件事:
当然,如果你要解析真实的的CSV文件,你应该使用CSV解析器。下面是一个阅读CSV文件并将其输出写入TSV(制表符分隔)文件的最小示例。如果这是你在一个名为
example.csv
的文件中的输入:您可以从文件中读取它,并使用制表符作为分隔符写入它,如下所示:
库从文件扩展名中猜测字段分隔符。在这里它正确地猜测'csv'表示逗号“”,'tsv'表示制表符。我们可以使用
cat -t
使制表符显式可见。klsxnrf14#
我怎样才能把这些组合成一个 predicate 呢?
...微观测试...