在 Elm 中拆分列表
List split in Elm
写一个函数把一个列表分成两个列表。第一部分的长度由调用者指定。
我是 Elm 的新手,所以我不确定我的推理是否正确。我认为我需要转换数组中的输入列表,以便我能够按提供的输入编号对其进行切片。我也在语法上苦苦挣扎。到目前为止,这是我的代码:
listSplit: List a -> Int -> List(List a)
listSplit inputList nr =
let myArray = Array.fromList inputList
in Array.slice 0 nr myArray
所以我想 return 一个包含 2 个列表(指定长度的第一个)的列表,但我被语法困住了。我该如何解决这个问题?
使用List.foldl
split : Int -> List a -> (List a, List a)
split i xs =
let
f : a -> (List a, List a) -> (List a, List a)
f x (p, q) =
if List.length p >= i then
(p, q++[x])
else
(p++[x], q)
in
List.foldl f ([], []) xs
- 当列表
p
达到所需长度时,将元素 x
附加到第二个列表 q
。
- 将元素
x
添加到列表 p
否则。
通常在 Elm 中,您使用 List
作为值序列。 Array
专门用于快速索引访问。
在函数式编程中处理列表时,请尝试根据 map
、filter
和 fold
来思考。它们应该是您所需要的。
对于return一对东西(例如两个列表),使用元组。 Elm 支持最多三个元素的元组。
此外,还有一个函数 splitAt in the List.Extra 包可以做完全相同的事情,尽管出于学习的目的最好自己动手做。
备选实施:
split : Int -> List a -> (List a, List a)
split i xs =
(List.take i xs, List.drop i xs)
我将尝试一个简单的递归定义,因为学习函数式编程的很大一部分是理解递归(foldl 只是其抽象):
split : Int -> List a -> (List a, List a)
split splitPoint inputList =
splitHelper splitPoint inputList []
{- We use a typical trick here, where we define a helper function
that requires some additional arguments. -}
splitHelper : Int -> List a -> List a -> (List a, List a)
splitHelper splitPoint inputList leftSplitList =
case inputList of
[] ->
-- This is a base case, we end here if we ran out of elements
(List.reverse leftSplitList, [])
head :: tail ->
if splitPoint > 0 then
-- This is the recursive case
-- Note the typical trick here: we are shuffling elements
-- from the input list and putting them onto the
-- leftSplitList.
-- This will reverse the list, so we need to reverse it back
-- in the base cases
splitHelper (splitPoint - 1) tail (head :: leftSplitList)
else
-- here we got to the split point,
-- so the rest of the list is the output
(List.reverse leftSplitList, inputList)
写一个函数把一个列表分成两个列表。第一部分的长度由调用者指定。
我是 Elm 的新手,所以我不确定我的推理是否正确。我认为我需要转换数组中的输入列表,以便我能够按提供的输入编号对其进行切片。我也在语法上苦苦挣扎。到目前为止,这是我的代码:
listSplit: List a -> Int -> List(List a)
listSplit inputList nr =
let myArray = Array.fromList inputList
in Array.slice 0 nr myArray
所以我想 return 一个包含 2 个列表(指定长度的第一个)的列表,但我被语法困住了。我该如何解决这个问题?
使用List.foldl
split : Int -> List a -> (List a, List a)
split i xs =
let
f : a -> (List a, List a) -> (List a, List a)
f x (p, q) =
if List.length p >= i then
(p, q++[x])
else
(p++[x], q)
in
List.foldl f ([], []) xs
- 当列表
p
达到所需长度时,将元素x
附加到第二个列表q
。 - 将元素
x
添加到列表p
否则。
通常在 Elm 中,您使用 List
作为值序列。 Array
专门用于快速索引访问。
在函数式编程中处理列表时,请尝试根据 map
、filter
和 fold
来思考。它们应该是您所需要的。
对于return一对东西(例如两个列表),使用元组。 Elm 支持最多三个元素的元组。
此外,还有一个函数 splitAt in the List.Extra 包可以做完全相同的事情,尽管出于学习的目的最好自己动手做。
备选实施:
split : Int -> List a -> (List a, List a)
split i xs =
(List.take i xs, List.drop i xs)
我将尝试一个简单的递归定义,因为学习函数式编程的很大一部分是理解递归(foldl 只是其抽象):
split : Int -> List a -> (List a, List a)
split splitPoint inputList =
splitHelper splitPoint inputList []
{- We use a typical trick here, where we define a helper function
that requires some additional arguments. -}
splitHelper : Int -> List a -> List a -> (List a, List a)
splitHelper splitPoint inputList leftSplitList =
case inputList of
[] ->
-- This is a base case, we end here if we ran out of elements
(List.reverse leftSplitList, [])
head :: tail ->
if splitPoint > 0 then
-- This is the recursive case
-- Note the typical trick here: we are shuffling elements
-- from the input list and putting them onto the
-- leftSplitList.
-- This will reverse the list, so we need to reverse it back
-- in the base cases
splitHelper (splitPoint - 1) tail (head :: leftSplitList)
else
-- here we got to the split point,
-- so the rest of the list is the output
(List.reverse leftSplitList, inputList)