4 2 1 載入和解析資料

2021-05-24 23:39:56 字數 4010 閱讀 5051

4.2.1 載入和解析資料

作為第一步,我們將實現乙個函式 convertdatarow,它從這個 csv 檔案中取一行作為字串,從這一行中返回兩個元件到乙個元組中。實現這個函式後,立刻測試它,通過給它乙個示例輸入 (字串「testing reading,1234」),應該能正確解析。在清單 4.2 中,可以這個函式的**和測試的結果。

listing 4.2 parsing a row from the csv file (f# interactive)

> open system;;

> let convertdatarow(csvline:string) =

let cells = list.ofseq(csvline.split(','))

match cells with

| title::number::_ –>

let parsednumber = int32.parse(number)

(title, parsednumber)

| _ -> failwith "incorrect data format!"

;; val convertdatarow : string -> string * int

> convertdatarow("testing reading,1234");;

val it : string * int = ("testing reading", 1234)

啟動 f# interactive 以後,我們從 system 命名空間匯入功能。我們需要開啟這個命名空間,因為**要使用 int32.parse 方法。這必須顯式匯入,反之,來自核心 f# 庫的函式,比如,list.ofseq,能隱式使用。

函式 convertdatarow 取乙個字串作為引數值,並把它拆分成使用逗號作為分隔符的值的列表,然後,用標準的 .net 的 split 方法執行此操作。當呼叫乙個值的例項方法時,f# 編譯器需要提前知道這個值的型別。不幸的是,在這種情況下,型別推斷沒有任何其他方式來推斷出型別,所以,我們要使用的型別批註顯式宣告 csvline 的型別是字串。

split 方法使用 c# 的 params 關鍵字宣告,取數量可變的字元作為引數值。我們指定只是乙個分隔符:逗號。這個方法的結果是乙個字串陣列,但我們想要使用的是列表,所以,要將結果轉換為列表,使用來自 f # list 模組的 ofseq 函式。我們將在第 10 和 12 章中討論有關陣列和其他集合型別。

一旦我們有了這個列表,就可以用 match 結構來測試,看格式是否正確。如果它包含兩個或多個值,將匹配第一種情況(title::number:: _),標題賦給值 title、數值賦給 number,其餘列(如果有)將被忽略。在這個分支中,我們使用 int32.parse 把字串轉換為整數,並返回乙個元組,包含標題和這個值。第二個分支觸發標準的 .net 異常。

如果你看這個簽名,可以發現該函式取乙個字串,並返回乙個元組,第乙個值是字串,第二個值是整數。這是完全符合我們的預期:標題返回作為乙個字串,第二列的數值轉換為整數。在下一行演示如何在 f# interactive 中方便地測試這個函式。示例呼叫的結果是乙個元組,包含「testing reading」 作為標題,"1234"作為數值。

在 f# 中使用 .net 字串

在 f# 中使用 .net 字串,一般會使用通常的 .net 方法。讓我們看看如何在 f# 中使用它們,先選幾個在 string 類中的靜態方法,我們可以使用這些方法,就好像普通的 f# 函式(使用 string 類名)。這些函式的引數值必須在括號內指定,作為以逗號分隔的元組。在這個型別簽名中,元組寫成星號:

■ string.concat (過載):接受可變數量的字串型別或物件的引數值,並返回乙個字串,通過把所有的這些都起來:

> string.concat("1 + 3", 3);;

val it : string = "1 + 33"

■ string.join (sep:string * strs:string) : string:連線乙個字串陣列 strs,使用指定的分隔符 sep,可以使用 [| ... |] 語法來構建陣列文字:

> string.join(", ", [| "1"; "2"; "3" |]);;

val it : string = "1, 2, 3"

.net 中的字串也是物件,也有例項成員,能在 f# 中使用,用典型的點表示法。在前面的示例中,我們已經看到這個,當拆分字串jf ,使用了 str.split 。下面的示例假定我們有乙個字串 str 包含"hello world!":

■ str.length:屬性,返回字串的長度,在 f# 中訪問屬性的方式與 c# 是相同的,所以讀取屬性不跟大括號:

> str.length;;

val it : int = 12

■ str.[index:int]:指定乙個字串的索引,寫在方括號內,返回由 index 指定的位置的字元。注意,在方括號(前)的前面仍需要點,不像 c#:

> str.[str.length - 1];;

val it : char = '!'

我們還可以使用 fsharp.powerpack.dll 庫中的可用函式。f# 中大多數的字串處理**可以使用 .net 方法來實現。

在前面的清單中,我們實現了 convertdatarow 函式,取來自 csv 檔案一行的字串,返回乙個元組,包含乙個標籤和乙個數值。下一步,我們將實現乙個函式,取乙個字串列表,將每個字串轉換為元組,使用 convertdatarow。清單 4.3 顯示了這個函式,然後,立即測試,解析乙個示例字串列表。

listing 4.3 parsing multiple lines from the input file (f# interactive)

> let rec processlines(lines) =

match lines with

| ->

| currentline::remaining ->

let parsedline = convertdatarow(currentline)

let parsedrest = processlines(remaining)

parsedline :: parsedrest

;;val processlines : string list -> (string * int) list

> let testdata = processlines ["test1,123"; "test2,456"];;

val testdata : (string * int) list =

[("test1", 123); ("test2", 456)]

這個函式在很多方面類似於我們在前一章實現的處理列表。正如你所看到的,宣告這個函式用了 let rec 關鍵字,所以,它是遞迴的。它取乙個字串列表作為引數值(lines),使用模式匹配,測試列表是空的列表,還是cons cell。對於空列表,它直接返回元組的空列表。如果模式匹配執行的分支是針對 cons cell 的,它會從列表中的第乙個元素的值賦給 currentline,包含剩餘元素的列表賦給 remainning。此分支的**首先處理單行,使用清單 4.2 的 convertdatarow 函式,然後,以遞迴方式處理列表中的其餘部分。最後,**構造乙個新的cons cell,包含:正在處理的行作為頭,以遞迴方式處理列表中的其餘部分作為尾。這意味著,對列表中的每個字串,函式執行 convertdatarow,並把收集到的結果為新的列表。

為更好地理解 processlines 函式做了什麼,我們還可以通過 f# interactive,檢視列印出的型別簽名。表明該函式取乙個字串列表(string list 型別)作為引數值,並返回包含型別為元組(strings * int)的列表。這正是完全解析一行的函式返回的型別,就好像是這個函式做了正確的事。我們通過呼叫示例列表作為引數值,驗證這一點,可以看到,由 f# interactive 列印出的呼叫的結果:它是包含兩個元組的列表,元組有乙個字串和乙個數字,所以,函式執行良好。

現在,我們有了乙個函式,將字串列表轉換為一種資料結構,將用在我們的圖表繪製應用程式中。在我們可以實現關鍵的資料處理部分之前,還需要看乙個簡單的工具程式。

preload 讓載入和解析解耦

一般寫html頁面,script寫在body結束標籤前,這樣只有當遇到script標籤的時候,才會載入執行,費載入時間不科學吖!儘管大多數基於標記語言的資源能被瀏覽器的預載入器 preloader 提前載入,但還是不盡如人意!preload大白話的意思是,嗨,瀏覽器!這個資源在這個頁面後面會用到,現...

HTML頁面載入和解析流程詳細介紹

利用瀏覽器的f12將網頁 複製下來,儲存在txt檔案中。再在瀏覽器中開啟,網頁顯示不正確的原因 1.原網頁引用了部分css js檔案,而複製下來的只是html文字 2.txt檔案存在編碼問題,最好不要將網頁往txt文字中儲存 為什麼有的網頁在谷歌瀏覽器中顯示正常,在ie中空白 原因 ie核心的瀏覽器...

Json資料封裝和解析

新增dll引用 右鍵專案 新增引用 net 選擇 c program files x86 reference assemblies microsoft framework v3.0 system.runtime.serialization.dll c program files x86 refere...