在 Elm 中,如何获得列表中的每个偶数索引和 return 作为另一个列表?
In Elm, how would you get every even index in a list and return as another list?
在 Elm 中,如何获取列表中的每个偶数索引并 return 作为另一个列表?
所以您只想 return 列表中的偶数索引项,对吗?
以下是编写自己的函数的方法。我们将编写一个辅助函数 everySecond_
,它看起来像这样。
everySecond_ : List a -> Int -> List a
everySecond_ list index =
case list of
[] ->
[]
hd :: tl ->
if index % 2 == 0 then
hd :: (everySecond_ tl (index + 1))
else
everySecond_ tl (index + 1)
此函数接受一个列表,以及一个表示该列表的当前头部具有的索引的数字。我们需要将其作为参数传递给函数。
然后我们进行模式匹配就行了。如果它是空的,我们 return 一个空列表;这标志着递归的结束。列表中的最后一个元素始终是一个空列表。如果它 不是 一个空列表,我们取头(第一个元素)和尾(代表所有内容的列表)。
如果我们的 index
参数是偶数(% 2 == 0
表示 "when divided by two, leaves no remainders"),我们想保留这个元素,所以我们将它附加到我们正在构建的列表的前面向上,并通过使用当前列表的尾部和递增的索引号再次调用 everySecond_
继续构建。
如果不是偶数,我们不想保留这个元素,所以我们只是return everySecond_ tl (index + 1)
,链表的下一阶段,然后重复该过程。
这就是它的逻辑。但这意味着我们需要调用 everySecond_ [foo, bar, baz] 1
来使用我们的函数,始终传入 1 作为默认参数。这不直观。这就是为什么我们用下划线称它为 everySecond_
的原因——这不是我们要让人们调用的,这是一个将存在于幕后的辅助函数。我们可以把它藏在后面
everySecond : List a -> List a
everySecond list =
everySecond_ list 1
现在你调用 everySecond [foo, bar, baz]
并且它工作正常,基本上默认起始索引为 1。
一种更简单的方法是根本不跟踪索引,而是使用布尔值 (True/False)。你从一个 False 开始,而不是测试是否被 2 整除,你只是检查布尔值。如果为 True,则保留该元素,并使用 False 再次调用该函数;如果为 False,则忽略该元素并使用 True 再次调用该函数。
大多数时候,您不需要编写递归函数,因为您可以使用标准的辅助函数来为您完成。这是针对您的特定问题的解决方案:
takeEvenIndexes : List a -> List a
takeEvenIndexes l =
l
|> List.indexedMap (\ i x -> if i |> modBy 2 == 0 then Just x else Nothing)
|> List.filterMap identity
indexedMap
function is like a map
but you can depend on the index of the value as well. And filterMap
is like a map but you can discard some of the values by returning Nothing
. Here it is applied to the identity
函数,因为在上一行已经预先计算了过滤。
在 Elm 中,如何获取列表中的每个偶数索引并 return 作为另一个列表?
所以您只想 return 列表中的偶数索引项,对吗?
以下是编写自己的函数的方法。我们将编写一个辅助函数 everySecond_
,它看起来像这样。
everySecond_ : List a -> Int -> List a
everySecond_ list index =
case list of
[] ->
[]
hd :: tl ->
if index % 2 == 0 then
hd :: (everySecond_ tl (index + 1))
else
everySecond_ tl (index + 1)
此函数接受一个列表,以及一个表示该列表的当前头部具有的索引的数字。我们需要将其作为参数传递给函数。
然后我们进行模式匹配就行了。如果它是空的,我们 return 一个空列表;这标志着递归的结束。列表中的最后一个元素始终是一个空列表。如果它 不是 一个空列表,我们取头(第一个元素)和尾(代表所有内容的列表)。
如果我们的 index
参数是偶数(% 2 == 0
表示 "when divided by two, leaves no remainders"),我们想保留这个元素,所以我们将它附加到我们正在构建的列表的前面向上,并通过使用当前列表的尾部和递增的索引号再次调用 everySecond_
继续构建。
如果不是偶数,我们不想保留这个元素,所以我们只是return everySecond_ tl (index + 1)
,链表的下一阶段,然后重复该过程。
这就是它的逻辑。但这意味着我们需要调用 everySecond_ [foo, bar, baz] 1
来使用我们的函数,始终传入 1 作为默认参数。这不直观。这就是为什么我们用下划线称它为 everySecond_
的原因——这不是我们要让人们调用的,这是一个将存在于幕后的辅助函数。我们可以把它藏在后面
everySecond : List a -> List a
everySecond list =
everySecond_ list 1
现在你调用 everySecond [foo, bar, baz]
并且它工作正常,基本上默认起始索引为 1。
一种更简单的方法是根本不跟踪索引,而是使用布尔值 (True/False)。你从一个 False 开始,而不是测试是否被 2 整除,你只是检查布尔值。如果为 True,则保留该元素,并使用 False 再次调用该函数;如果为 False,则忽略该元素并使用 True 再次调用该函数。
大多数时候,您不需要编写递归函数,因为您可以使用标准的辅助函数来为您完成。这是针对您的特定问题的解决方案:
takeEvenIndexes : List a -> List a
takeEvenIndexes l =
l
|> List.indexedMap (\ i x -> if i |> modBy 2 == 0 then Just x else Nothing)
|> List.filterMap identity
indexedMap
function is like a map
but you can depend on the index of the value as well. And filterMap
is like a map but you can discard some of the values by returning Nothing
. Here it is applied to the identity
函数,因为在上一行已经预先计算了过滤。