如何在 elm 中将一个列表分成四个列表?
How do I split a list in to four lists in elm?
我有一个必须呈现的项目列表。我有一个名为 viewItem
的函数,它可以呈现一个项目。我做了一个简单的 List.map viewItem items
,现在我有了一个可以显示的项目列表。
我的视图有四列。如何将此列表拆分为包含原始列表中所有元素的四个列表?
这就是我现在的做法,但一定有我遗漏的地方。我希望能够将它分成五列甚至六列,而不必每次都写 col4 = ...
和 col5 = ...
。
splitColumns : Int -> Array a -> Array (List a)
splitColumns cnum xs =
let
ixdList =
Array.toIndexedList xs
in
List.filterMap
(\a ->
if modBy 4 (Tuple.first a) == cnum then
Just (Tuple.second a)
else
Nothing
)
ixdList
viewItems : Array Item -> Html msg
viewItems items =
let
itemsHtml =
Array.map viewItem items
col0 =
splitColumns 0 itemsHtml
col1 =
splitColumns 1 itemsHtml
col2 =
splitColumns 2 itemsHtml
col3 =
splitColumns 3 itemsHtml
in
main_
[ class "section" ]
[ Html.div
[ class "container" ]
[ Html.div
[ class "columns" ]
[ Html.div
[ class "column" ]
col0
, Html.div
[ class "column" ]
col1
, Html.div
[ class "column" ]
col2
, Html.div
[ class "column" ]
col3
]
]
]
您可以将 List.map
与 List.range
一起使用。 List.range a b
生成从 a
到 b
(含)的整数列表。
你的 viewItems
功能因此大大简化:
viewItems : Array Item -> Html msg
viewItems items =
main_
[ class "section" ]
[ Html.div
[ class "container" ]
[ Html.div
[ class "columns" ]
List.map (\n -> Html.div [ class "column" ] (splitColumns n (Array.map viewItem items)) (List.range 0 3)
]
]
如果你想支持不同的列数,当然可以把splitColumns
中的hard-coded4
换成一个参数
您可以将您当前的方法重写为只进行一次的折叠,如下所示:
cols : List a -> { col0 : List a, col1 : List a, col2 : List a, col3 : List a }
cols list =
list
|> List.foldl
(\x ( i, cols ) ->
case modBy 4 i of
0 ->
( i + 1, { cols | col0 = x :: cols.col0 } )
1 ->
( i + 1, { cols | col1 = x :: cols.col1 } )
2 ->
( i + 1, { cols | col2 = x :: cols.col2 } )
3 ->
( i + 1, { cols | col3 = x :: cols.col3 } )
_ ->
( i + 1, cols )
)
( 0, { col0 = [], col1 = [], col2 = [], col3 = [] } )
|> Tuple.second
这也在内部跟踪索引,因此不需要您为其提供索引列表,但它仍然是 hard-coded 四列。如果我们希望能够将它用于任意数量的列,我们必须使用可以按顺序容纳任意数量项目的数据结构。数组非常适合这个,允许我们使用使用 modBy
:
计算的索引更新它
cols : Int -> List a -> List (List a)
cols n list =
list
|> List.foldl
(\x ( i, cols ) ->
let
index =
modBy n i
tail =
cols |> Array.get index |> Maybe.withDefault []
in
( i + 1, Array.set index (x :: tail) cols )
)
( 0, Array.repeat n [] )
|> Tuple.second
|> Array.toList
然后我们可以在视图函数中使用List.map
来渲染它们:
viewItems : Array Item -> Html msg
viewItems items =
let
itemsHtml =
Array.map viewItem items
|> Array.toList
in
main_
[ class "section" ]
[ Html.div
[ class "container" ]
[ Html.div
[ class "columns" ]
(cols 4 itemsHtml |> List.map (Html.div [ class "column" ]))
]
]
我有一个必须呈现的项目列表。我有一个名为 viewItem
的函数,它可以呈现一个项目。我做了一个简单的 List.map viewItem items
,现在我有了一个可以显示的项目列表。
我的视图有四列。如何将此列表拆分为包含原始列表中所有元素的四个列表?
这就是我现在的做法,但一定有我遗漏的地方。我希望能够将它分成五列甚至六列,而不必每次都写 col4 = ...
和 col5 = ...
。
splitColumns : Int -> Array a -> Array (List a)
splitColumns cnum xs =
let
ixdList =
Array.toIndexedList xs
in
List.filterMap
(\a ->
if modBy 4 (Tuple.first a) == cnum then
Just (Tuple.second a)
else
Nothing
)
ixdList
viewItems : Array Item -> Html msg
viewItems items =
let
itemsHtml =
Array.map viewItem items
col0 =
splitColumns 0 itemsHtml
col1 =
splitColumns 1 itemsHtml
col2 =
splitColumns 2 itemsHtml
col3 =
splitColumns 3 itemsHtml
in
main_
[ class "section" ]
[ Html.div
[ class "container" ]
[ Html.div
[ class "columns" ]
[ Html.div
[ class "column" ]
col0
, Html.div
[ class "column" ]
col1
, Html.div
[ class "column" ]
col2
, Html.div
[ class "column" ]
col3
]
]
]
您可以将 List.map
与 List.range
一起使用。 List.range a b
生成从 a
到 b
(含)的整数列表。
你的 viewItems
功能因此大大简化:
viewItems : Array Item -> Html msg
viewItems items =
main_
[ class "section" ]
[ Html.div
[ class "container" ]
[ Html.div
[ class "columns" ]
List.map (\n -> Html.div [ class "column" ] (splitColumns n (Array.map viewItem items)) (List.range 0 3)
]
]
如果你想支持不同的列数,当然可以把splitColumns
中的hard-coded4
换成一个参数
您可以将您当前的方法重写为只进行一次的折叠,如下所示:
cols : List a -> { col0 : List a, col1 : List a, col2 : List a, col3 : List a }
cols list =
list
|> List.foldl
(\x ( i, cols ) ->
case modBy 4 i of
0 ->
( i + 1, { cols | col0 = x :: cols.col0 } )
1 ->
( i + 1, { cols | col1 = x :: cols.col1 } )
2 ->
( i + 1, { cols | col2 = x :: cols.col2 } )
3 ->
( i + 1, { cols | col3 = x :: cols.col3 } )
_ ->
( i + 1, cols )
)
( 0, { col0 = [], col1 = [], col2 = [], col3 = [] } )
|> Tuple.second
这也在内部跟踪索引,因此不需要您为其提供索引列表,但它仍然是 hard-coded 四列。如果我们希望能够将它用于任意数量的列,我们必须使用可以按顺序容纳任意数量项目的数据结构。数组非常适合这个,允许我们使用使用 modBy
:
cols : Int -> List a -> List (List a)
cols n list =
list
|> List.foldl
(\x ( i, cols ) ->
let
index =
modBy n i
tail =
cols |> Array.get index |> Maybe.withDefault []
in
( i + 1, Array.set index (x :: tail) cols )
)
( 0, Array.repeat n [] )
|> Tuple.second
|> Array.toList
然后我们可以在视图函数中使用List.map
来渲染它们:
viewItems : Array Item -> Html msg
viewItems items =
let
itemsHtml =
Array.map viewItem items
|> Array.toList
in
main_
[ class "section" ]
[ Html.div
[ class "container" ]
[ Html.div
[ class "columns" ]
(cols 4 itemsHtml |> List.map (Html.div [ class "column" ]))
]
]