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条答案
按热度按时间0g0grzrc1#
其他人给出了一些建议和很多代码。使用SWI-Prolog,要解析逗号分隔的整数,您可以使用library(dcg/basics)和library(dcg/high_order)来简单地执行此操作:
字符串
当然,如果你试图解析真实的的CSV文件,你应该使用CSV解析器。下面是一个阅读CSV文件并将其输出写入TSV(制表符分隔)文件的最小示例。如果这是您在名为
example.csv
的文件中的输入:型
您可以从文件中读取它,并使用制表符作为分隔符,如下所示:
型
库根据文件扩展名猜测字段分隔符。在这里,它正确地猜到了'csv'是指逗号“,'tsv'是指制表符。我们可以使用
cat -t
显式显示选项卡。型
3df52oht2#
我不知道一个特别的新手友好的方式来做到这一点,不妥协的地方。这是最简单的:
字符串
但它会产生并留下虚假的选择点,这有点烦人。
这削减了choicepoints,这在使用它时很好,但在不知道这意味着什么的情况下进行的练习很糟糕:
型
这使用了if/else,这是更少的代码:
型
但是是logically bad and you should reify the branching with if_,它不是内置在SWI Prolog中的,使用起来不那么简单。
或者你可以用DCG写一个语法,这不是新手的领域:
型
例如。
型
但是现在你又回到了它,在解析 * 和 * 时留下了虚假的选择点,你必须处理SWI Prolog中字符串/原子/字符代码的历史性分裂;由于double_quotes标志,该列表将与
"11,22,33,44,55"
统一,但看起来不会。62lalag43#
split_string不可逆。可以使用DCG -这里是一个简单的CSV多行DCG解析器:
字符串
为了证明可逆性:
型
要解析字段内容并保持可逆性,可以使用例如atom_codes。
lo8azlld4#
如何将这些组合成一个 predicate ?
字符串
。微测试。。
型