如何在elm脚本中将类添加到表的所有列
elm脚本从后端代码获取csv字符串如何在elm脚本中将类添加到表的所有列,elm,Elm,elm脚本从后端代码获取csv字符串csv。我想创建一个表,每个单元格的类名应该是列名 表格的行可以从rows=String.split“\n”csv中获得。如果我不需要定义类,可以通过在行上应用双嵌套List.map来创建表。但为了给每个单元格赋予类,我需要保存包含列(或类)名称的行的第一个元素,并将其与剩余的每一行配对。由于elm中没有for循环,我的策略是定义一个递归函数来创建所有tr元素,并使用List.map连接tr元素。此函数的输入是第一行名为names,另一行名为cols。它们都是
csv
。我想创建一个表,每个单元格的类名应该是列名
表格的行可以从rows=String.split“\n”csv
中获得。如果我不需要定义类,可以通过在行上应用双嵌套List.map
来创建表。但为了给每个单元格赋予类,我需要保存包含列(或类)名称的行的第一个元素,并将其与剩余的每一行配对。由于elm中没有for循环,我的策略是定义一个递归函数来创建所有tr
元素,并使用List.map
连接tr
元素。此函数的输入是第一行名为names
,另一行名为cols
。它们都是列表字符串
。每次运行时,它都使用两个列表的头(从List.head
)创建一个td
,然后传递两个列表的其余元素(从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
createRow名称cols=
凯科斯
[]->文本“”
_ ->
让
c0=(列表头列)
c=(List.drop 1列)
n0=(列表标题名称)
n=(List.drop 1名称)
在里面
td[][text在递归函数中,您需要传递(部分计算的)结果,以便在每次调用中对其进行修改,并在完成递归后返回。因此,这可能类似于:
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 ])
type alias Csv =
{ headers : List String
, records : List (List String)
}
这里还有几个值得注意的变化:
- 我使用模式匹配从其余的列表中提取
cols
列表的头部(也称为尾部)
List.head
返回一个可能是一个
(在本例中,a
是字符串
),因此我添加了对可能的调用。使用默认值
- 由于
cols
是一个列表字符串
,因此您不需要调用toString
,并且可以将其直接传递给text
- 第一次调用此函数时,将为
单元格
参数传入[]
首先,我建议您不要手动解析CSV。package manager上有多个CSV解析器,因此我们可以将重点放在如何处理这些值上
是一个选项,但它们在解析后都会为您提供一个Csv
类型,如下所示:
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 ])
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
是递归的,用于命令式语言中的循环(“对于此列表中的每个项目,应用此函数并在另一个列表中收集结果”)但是,它不知道传递给它的值的类型,允许我们专注于转换值。您能给出函数输入和输出的示例吗?您在描述中提到了tr
s,但代码中没有tr
s,只有td
。