Add calculated key to collection

穿精又带淫゛_ 提交于 2019-12-23 16:24:45

问题


Please consider this dataset, composed by man and woman, and that I filter in a second moment according to few variables:

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}]

Lets suppose that I would like to add a fourth key "body mass index" or "bmi", and that its value is roughly given by "weight"/"height". Hence I expect:

[{"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)}]

I thought that map.Add may help.

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

Unfortunately, it returns an error:

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

I am sure there are further errors in my code, but without this function I cannot actually look for them. Am I, at least, approaching the problem correctly?


回答1:


Creating modified versions of the JSON is sadly one thing that the F# Data type provider does not make particularly easy. What makes that hard is the fact that we can infer the type from the source JSON, but we cannot "predict" what kind of fields people might want to add.

To do this, you'll need to access the underlying representation of the JSON value and operate on that. For example:

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()


来源:https://stackoverflow.com/questions/40893531/add-calculated-key-to-collection

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!