2011-09-20 261 views
0

我以這種形式解析字符串的記錄:解析分隔符分隔值

description: double/double/double 

爲前:

item description: 0.4/8/-24.66 

每個記錄應該導致的對象:

new MyObj("first item", 0.4, 2.4, -24.66) 

我可以使用正則表達式和過程方法輕鬆完成此操作,但生成的代碼易於出錯且相當難看(至少從功能角度來看)。

這怎麼能以更優雅的方式完成?

回答

2

或者,你可以創建一個簡單的解析函數string->MyObj這樣的:

type MyObj(descr:string, a:float, b:float, c:float) = 
    override this.ToString() = 
     System.String.Format("{0}: {1}; {2}; {3}", descr,a,b,c) 

let myobjfromstr (str:string) = 
    let flds = str.Split([|':';'/'|]) 
    let ip s = System.Double.Parse(s)  
    new MyObj(flds.[0], ip flds.[1], ip flds.[2], ip flds.[3]) 

myobjfromstr "item description: 0.4/8/-24.66" |> printfn "%A" 

更新:我猜的記錄是由新線或類似的東西分離,被分成一個列表關於第二個想法,在你的問題中沒有這樣的東西......)

+0

簡單但有效,我喜歡它!記錄由換行符分隔,很抱歉沒有提及它。 –

+0

@FrancescoDeVittori,同樣值得注意的是,可以創建一個像'string-> seq '這樣的函數,這是imho,非常F# - 轉義。另外,Don Syme在他的書中寫道,只要它給你提供必要的性能並且隱藏在函數或類型中,你就不應該害怕可變域和過程方法......希望這會有所幫助。 – Dmitry

4

好,FParsec是好的:

#r "FParsecCS.dll" 
#r "FParsec.dll" 

open FParsec 

let parser : Parser<_,unit> = 
    sepBy pfloat (pchar '/') 

然後run parser "0.4/8/-24.66"回報val it : ParserResult<float list,unit> = Success: [0.4; 8.0; -24.66]

+0

看起來不錯,除了我還需要記錄的第一部分(冒號前的字符串)。我也會對不使用外部庫的解決方案感興趣。 –

+0

對於第一部分你可以做many1Chars(notAnyOf [':'])。>> skipChar':'''。對於不使用外部庫,不要使用FParsec :) –