Сначала я бы посоветовал вам не анализировать CSV вручную. В диспетчере пакетов доступно несколько анализаторов CSV, поэтому мы можем вместо этого сосредоточиться на том, что делать со значениями.
https://package.elm -lang.org / пакеты / периодические / вяз-CSV / последний / Csv
это вариант, но после синтаксического анализа все они дают тип Csv
, который выглядит следующим образом:
type alias Csv =
{ headers : List String
, records : List (List String)
}
Как вы уже говорили, заголовков столько, сколько значений в каждой строке (иначе CSV не будет действительным). Отбрасывание / преобразование через рекурсию может выполнить работу, но мы можем быть более декларативными, полагаясь на операции со списками для выполнения основной части работы:
classTable : Csv -> Html msg
classTable csv =
table []
(csv.records |> List.map (tableRow csv.headers))
tableRow : List String -> List String -> Html msg
tableRow headers values =
let
insertNextCellInRow ( header, value ) row =
td [ class header ] [ text value ] :: row
in
tr []
(List.map2 Tuple.pair headers values
|> List.foldr insertNextCellInRow []
)
Примечание: List.foldr
является рекурсивным и служит циклу на императивном языке («для каждого элемента в этом списке примените эту функцию и соберите результаты в этом другом списке»). Однако он не зависит от типов значений, передаваемых ему, и позволяет нам сосредоточиться на преобразовании значений.