2016-11-30 48 views
2

請考慮此數據集,由男人和女人組成的,而我根據幾個變量在第二時刻過濾:添加計算關鍵收集

type ls = JsonProvider<"..."> 
let dt = ls.GetSamples() 

let dt2 = 
dt |> Seq.filter (fun c -> c.Sex = "male" && c.Height > Some 150) 

dt2 

[{"sex":"male","height":180,"weight":85}, 
{"sex":"male","height":160" "weight":60}, 
{"sex":"male","height":180,"weight":85}] 

讓我們假設,我想補充的第四個關鍵「體重指數」或「bmi」,其值大致由「體重」/「身高」給出。因此,我預計:

[{"sex":"male","height":180,"weight":85, "bmi":(180/85)}, 
{"sex":"male","height":160" "weight":60, "bmi":(160/60}, 
{"sex":"male","height":180,"weight":85, "bmi":(180/85)}] 

我認爲map.Add可能有所幫助。

let dt3 = dt2.Add("bmi", (dt2.Height/dt2.Weight))  

不幸的是,它會返回一個錯誤:

error FS0039: The field, constructor or member 'Add' is not defined 

我肯定有我的代碼進一步的錯誤,但沒有這個功能,我不能真正尋找他們。至少,我是否正確地接近問題?

回答

3

創建JSON的修改版本很遺憾,F#數據類型提供程序並不特別容易。讓我們難以接受的是,我們可以從源JSON中推斷出這種類型,但我們無法「預測」人們想要添加的字段類型。

爲此,您需要訪問JSON值的基礎表示並對其進行操作。例如:

type ls = JsonProvider<""" 
    [{"sex":"male","height":180,"weight":85}, 
    {"sex":"male","height":160,"weight":60}, 
    {"sex":"male","height":180,"weight":85}]"""> 

let dt = ls.GetSamples() 

let newJson = 
    dt 
    |> Array.map (fun recd -> 
     // To do the calculation, you can access the fields via inferred types 
     let bmi = float recd.Height/float recd.Weight 

     // But now we need to look at the underlying value, check that it is 
     // a record and extract the properties, which is an array of key-value pairs 
     match recd.JsonValue with 
     | JsonValue.Record props -> 
      // Append the new property to the existing properties & re-create record 
      Array.append [| "bmi", JsonValue.Float bmi |] props 
      |> JsonValue.Record 
     | _ -> failwith "Unexpected format") 

// Re-create a new JSON array and format it as JSON 
JsonValue.Array(newJson).ToString() 
+0

其實我真的很難過。無論如何,它完美的作品,謝謝。我正在仔細研究它。我只有一個問題。以前,我用'let dt2 = dt |> Seq.filter(fun c - > c.Sex =「male」&& c.Height> 150)'過濾了數據集。這使'dt2'成爲一個序列,並且它不好。我如何將'dt2傳遞給'type ls = JsonProvider '以使其再次成爲json?如果你更舒適,我可以聊天。 – Worice

+1

您可以使用'Array.filter'進行過濾 - 這會將數據保存在數組中。 (或者,您可以在管道末端使用'Array.ofSeq')。 –