将字符串列表转换为数字列表(浮点数和整数)

时间:2017-04-30 13:45:10

标签: list types prolog

我在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]).来测试这是否是这样的,但最终结果是参数没有被充分实例化(当我们两个参数都应该是'?'时,我不明白这一点。类型,这意味着它们可以是输入和输出变量。

2 个答案:

答案 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//0whites//0number//1blanks_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符号的灵活性......