在Elm中,你如何获得列表中的每个偶数索引并返回另一个列表?
答案 0 :(得分:4)
大多数情况下,您不需要编写递归函数,因为您可以使用标准辅助函数来为您执行此操作。以下是针对您的具体问题的解决方案:
takeEvenIndexes : List a -> List a
takeEvenIndexes l =
l
|> List.indexedMap (\ i x -> if i % 2 == 0 then Just x else Nothing)
|> List.filterMap identity
indexedMap
函数类似于map
,但您也可以依赖于值的索引。 filterMap
就像一张地图,但您可以通过返回Nothing
来放弃一些值。这里它被应用于identity
函数,因为过滤已经在前一行预先计算过了。
答案 1 :(得分:2)
所以你想只从列表中返回偶数索引的项目,对吗?
在这里,您可以如何编写自己的功能。我们将编写一个辅助函数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)
此函数采用一个列表,以及一个数字,表示该列表当前头的索引。我们需要将它作为参数传递给函数。
然后我们在列表上进行模式匹配。如果它为空,我们返回一个空列表;这标志着递归的结束。列表中的最后一个元素始终是一个空列表。如果它的不是是一个空列表,我们采用头部(第一个元素)和尾部(表示一切的列表)。
如果我们的index
参数是偶数(% 2 == 0
表示"当除以2时,不留下余数"),我们要保留此元素,因此我们将其附加到我们正在建立的列表的前面,并通过使用当前列表的尾部和递增的索引号再次调用everySecond_
来继续构建。
如果它不,我们不想保留此元素,因此我们只返回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再次调用该函数。