2017-04-30 34 views
1

我有以下的文本文件中的數據,我從標準輸入讀取:轉換列表中列出的數字(包括浮點和整數)

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中?如何將字符串轉換爲整數或浮點基於'點'的存在?

我試着使用普通的atom_string(X, [1,.,5]).來測試這是否是這種方式,但它結束與參數沒有充分實例化(我不知道,當兩個參數應該是'?'類型這意味着它們可以是輸入和輸出變量

+1

使用'number_chars(X,[ '1', '5'])而不是!請注意,您必須爲字符1寫入'1',而不是單獨寫入'1'。 – false

+1

更加緊湊的是,當你使用set_prolog_flag(double_quotes,chars)時,你可以爲'['1',。,'5']寫''1.5'''。' – false

+1

'maplist(number_chars,Numbers,Strings)' – false

回答

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]]. 
0

以防萬一你仍然需要解析使用逗號作爲小數點分隔號,這裏是一個簡單的方法(更換數字// 1 number_// 1在DCG鮑里斯張貼):

number_(Number) --> 
    ( integer(Int), ",", integer(Frac) 
    -> {format(codes(Cs), '~d.~d', [Int, Frac]), number_codes(Number, Cs)} 
    ; number(Number) 
    ). 

它顯示了DCG符號如何靈活是...

+0

把'dot // 0'重新定義爲'dot - >「,」。'? –

+0

我不知道這種可能性,無論如何,(原始)樣本數據有混合大小寫(逗號和點分隔數字) – CapelliC

+0

我留下了這樣的印象:在問題中混合使用兩者是錯誤的,在我問到它之後,它由OP自己編輯。 –

相關問題