Как загрузить CSV с различными структурами, используя CSVProvider? - PullRequest
0 голосов
/ 12 июня 2018

Есть идеи?Мой текущий код ниже.

let rawdata csvfile 
        FinCsv.Load(data).Rows
        |> Seq.filter (fun row -> row.Id <> "---")
        |> Seq.filter (fun row -> row.Country <> "Honduras")
        |> Seq.filter (fun row -> row.Tax <> 0)
        |> Seq.groupBy (fun row -> row.Country)
        |> Seq.averageBy (fun row -> row.Tax)
        |> List.ofSeq

1 Ответ

0 голосов
/ 13 июня 2018

Проблема со статически разрешаемыми параметрами типов заключается в том, что синтаксис громоздок.Вот пример:

let inline snippet< ^T when ^T : (member Id : string)
                        and ^T : (member Country : string)
                        and ^T : (member Tax : float) >
                        xs =
    xs
    |> Seq.filter (fun row -> ( ^T : (member Id : string) row) <> "---")
    |> Seq.filter (fun row -> ( ^T : (member Country : string) row) <> "South America")
    |> Seq.filter (fun row -> ( ^T : (member Tax : float) row) <> 0.0)
    |> Seq.groupBy (fun row -> ( ^T : (member Country : string) row))
    |> Seq.map (fun (country, rows) -> country, (rows |> Seq.averageBy (fun row -> ( ^T : (member Tax : float) row))))
    |> List.ofSeq

(я изменил вызов averageBy, поэтому он имеет больше смысла, чем вопрос в вопросе.)

Вы можете позволить компилятору выводить ограничения довольночем объявить их явно:

let inline snippet xs =
    xs
    |> Seq.filter (fun row -> ( ^T : (member Id : string) row) <> "---")
    |> Seq.filter (fun row -> ( ^T : (member Country : string) row) <> "South America")
    |> Seq.filter (fun row -> ( ^T : (member Tax : float) row) <> 0.0)
    |> Seq.groupBy (fun row -> ( ^T : (member Country : string) row))
    |> Seq.map (fun (country, rows) -> country, (rows |> Seq.averageBy (fun row -> ( ^T : (member Tax : float) row))))
    |> List.ofSeq

В качестве альтернативы вы можете потребовать, чтобы вызывающая сторона передавала функции-получатели значений:

let snippet2 getId getCountry getTax xs =
    xs
    |> Seq.filter (fun row -> getId row <> "---")
    |> Seq.filter (fun row -> getCountry row <> "South America")
    |> Seq.filter (fun row -> getTax row <> 0.0)
    |> Seq.groupBy (fun row -> getCountry row)
    |> Seq.map (fun (country, rows) -> country, (rows |> Seq.averageBy (fun row -> getTax row))))
    |> List.ofSeq

Это позволяет несколько упростить синтаксис:

let snippet2 getId getCountry getTax xs =
    xs
    |> Seq.filter (getId >> (<>) "---")
    |> Seq.filter (getCountry >> (<>) "South America")
    |> Seq.filter (getTax >> (<>) 0.0)
    |> Seq.groupBy getCountry
    |> Seq.map (fun (country, rows) -> country, (rows |> Seq.averageBy getTax))
    |> List.ofSeq

Вы можете объявить специфичные для типа экземпляры функции с частичным применением:

let snippetForCsvFile1 (xs : CsvFile1 seq) = xs |> snippet2 (fun r -> r.Id) (fun r -> r.Country) (fun r -> r.Tax)

Тогда ваш переключатель может выглядеть так:

let rawdata csvfile =
    match csvfile with
    | 1 -> snippetForCsvFile1 CsvFile1
    | 2 -> snippetForCsvFile2 CsvFile2
    | 3 -> snippetForCsvFile3 CsvFile3
    | 4 -> snippetForCsvFile4 CsvFile4
    | _ -> failwith "Not a File"

Это тогда должноработайте со своим последним выражением:

let raw =
    [ 1 .. 4]
    |> List.collect rawdata

У переключателя в вашем вопросе есть проблема, о которой вы не упоминали в своем вопросе:

let rawdata csvfile =
    let data = 
        match csvfile with
        | 1 -> CsvFile1
        | 2 -> CsvFile2
        | 3 -> CsvFile3
        | 4 -> CsvFile4
        | _ -> failwith "Not a File"

Проблема здесь заключается в том, что привязкаdata не имеет ни одного типа.Этого можно добиться с помощью объектно-ориентированного подхода с использованием интерфейса (или базового класса), но это не будет особенно идиоматично для F #.Более идиоматическим подходом было бы объявить дискриминационный союз, но, учитывая приведенный вами пример, это не кажется необходимым.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...