2016-11-30 2 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> Some 150)'. Это делает последовательность 'dt2', и это не хорошо. Как я могу передать '' dt2 '' тип ls = JsonProvider ', чтобы снова сделать его json? Я могу поболтать, если вам удобнее. – Worice

+1

Вы можете просто использовать 'Array.filter' для фильтрации, который будет хранить данные в массиве. (Или вы можете использовать 'Array.ofSeq' в конце конвейера). –

Смежные вопросы