我在stdin中读取的文本文件中有以下数据:
4.5 12 -16
12 37 -43
-1.6 -4.3 98
1
2
3.3
我对它执行一些基本的解析并进入(想要的)点,我将其解析为结构如下:
[[[4,.,5],[1,2],[-,1,6]],[[1,2],[3,7],[-,4,3]],[[-,1,.,6],[-,4,.,3],[9,8]],[[]],[[1]],[[2]],[[3,.,3],[]]]
这基本上是一个行列表,其中行也是表示为字符列表的数字列表。现在我想将它转换为行列表,其中行将是一个数字列表 - 浮点数和整数值的混合列表。所以我的问题:在Prolog中甚至可以混合列表吗?如何根据'dot'的存在将字符串转换为整数或浮点数?
我尝试使用普通atom_string(X, [1,.,5]).
来测试这是否是这样的,但最终结果是参数没有被充分实例化(当我们两个参数都应该是'?'时,我不明白这一点。类型,这意味着它们可以是输入和输出变量。
答案 0 :(得分:3)
我猜不出你正在使用哪个Prolog,但是如果你使用的是SWI-Prolog,那么有一个很好的小库library(dcg/basics)
。它有点难以找到,但它具有用于解析的DCG原语,这使得这非常容易。如果您不使用SWI-Prolog,您可以复制库,或使用它在代码中的定义(确保阅读许可证!)。
所以这是SWI-Prolog中的解决方案:
:- use_module(library(dcg/basics)).
input_to_numbers(Input, Numbers) :-
phrase_from_stream(numbers(Numbers), Input).
numbers([]) --> eos, !.
numbers([Ns|Rest]) -->
nums_line(Ns), !,
numbers(Rest).
nums_line([N|Ns]) -->
whites,
number(N), !,
nums_line(Ns).
nums_line([]) --> blanks_to_nl.
它使用库中的以下DCG:eos//0
,whites//0
,number//1
和blanks_to_nl//0
。请注意,number//1
可以读取整数或浮点数,还可以读取写为1.7e3
的浮点数。
这个特定的实现坚持要读取每一行,对于没有数字的行,它会给你一个空列表。如果输入完全为空,它只能返回一个空列表!如果输入中有任何非数字,它将失败。但是一旦你有原语,很容易适应你的需要。
这是完整的代码,您只需要以某种方式提供示例文件。如果您想从"标准输入"进行操作,您可以使用user_input
作为输入流:
?- input_to_numbers(user_input, Ns).
|: 4.5 12 -16
|: 12 37 -43
|: -1.6 -4.3 98
|:
|: 1
|: 2
|: 3.3
Ns = [[4.5, 12, -16], [12, 37, -43], [-1.6, -4.3, 98], [], [1], [2], [3.3]].
所以我从顶层调用了这个,只是粘贴了内容并输入了Ctrl-D来放置文件结尾。如果您在文件中输入了输入,则可以执行以下操作:
?- setup_call_cleanup(open('nums.txt', read, In),
input_to_numbers(In, Ns),
close(In)).
In = <stream>(0x19a6740),
Ns = [[4.5, 12, -16], [12, 37, -43], [-1.6, -4.3, 98], [], [1], [2], [3.3]].
答案 1 :(得分:0)
如果您仍然需要使用逗号作为小数分隔符来解析数字,这里有一个简单的方法(在Boris发布的DCG中用数字_ // 1替换数字// 1):
number_(Number) -->
( integer(Int), ",", integer(Frac)
-> {format(codes(Cs), '~d.~d', [Int, Frac]), number_codes(Number, Cs)}
; number(Number)
).
它显示了DCG符号的灵活性......