как добавить класс во все столбцы таблицы в скрипте elm - PullRequest
0 голосов
/ 25 апреля 2019

Сценарии elm получают строку csv csv из внутреннего кода. Я хочу создать таблицу и имя класса каждой ячейки должно быть именем столбца .

Строки таблицы можно получить из rows = String.split "\n" csv. Если мне не нужно определять классы, таблицу можно создать, применив дважды вложенные List.map к rows. Но чтобы присвоить класс каждой ячейке, мне нужно сохранить первый элемент строки, который содержит имена столбцов (или классов), и связать его с каждой из оставшихся строк. Поскольку в elm цикла for нет, моя стратегия состоит в том, чтобы определить рекурсивную функцию для создания всех элементов tr и объединения элементов tr с использованием List.map. Ввод этой функции - первая строка с именем names, а другая строка с именем cols. Они оба List String. Каждый раз, когда он запускается, он создает td, используя заголовки (из List.head) двух списков, а затем передает оставшиеся элементы двух списков (из List.drop) для рекурсии. Но я не смог соединить два возвращенных компонента.

createRow names cols =
    case cols of
        [] -> text ""
        _ ->
            let
                c0 = (List.head cols)
                c = (List.drop 1 cols)
                n0 = (List.head names)
                n = (List.drop 1 names)
            in
                td [] [text <| toString <| c0]
                , createRow n c 

Что мне положить в блок in? Или есть лучший способ достичь моей цели?

Ответы [ 2 ]

4 голосов
/ 26 апреля 2019

Сначала я бы посоветовал вам не анализировать 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 является рекурсивным и служит циклу на императивном языке («для каждого элемента в этом списке примените эту функцию и соберите результаты в этом другом списке»). Однако он не зависит от типов значений, передаваемых ему, и позволяет нам сосредоточиться на преобразовании значений.

3 голосов
/ 26 апреля 2019

В рекурсивной функции вам нужно передать (частично вычисленный) результат, чтобы вы могли изменять его при каждом вызове и возвращать его после завершения рекурсии.Так что это может выглядеть примерно так:

createRow : List String -> List String -> List (Html msg) -> List (Html msg)
createRow names cols cells =
    case cols of 
        [] -> cells
        col :: remainingCols ->
            let
                name = 
                    names
                    |> List.head
                    |> Maybe.withDefault ""
                remainingNames = List.drop 1 names
                cell =
                    td [class name] [text col]
            in
            createRow remainingNames remaningCols (cells ++ [ cell ])

Несколько других заметных изменений:

  • Я использовал сопоставление с образцом, чтобы извлечь заголовок списка colsиз остальных (также называемых хвостом)
  • List.head возвращает Maybe a (в данном случае a равно String), поэтому я добавил вызов Maybe.withDefault
  • Поскольку cols является List String, вам не нужно звонить на toString, и вы можете передать его напрямую text
  • Когда вы вызываете эту функцию в первый раз, выпередам [] для аргумента cells
...