在Elm中,如何获取列表中的每个偶数索引并作为另一个列表返回?

在Elm中,如何获取列表中的每个偶数索引并作为另一个列表返回?,elm,Elm,在Elm中,如何获取列表中的每个偶数索引并作为另一个列表返回?所以您只想从列表中返回偶数索引项,对吗 下面是编写自己的函数的方法。我们将编写一个助手函数,everySecond\uu,如下所示 everySecond_ : List a -> Int -> List a everySecond_ list index = case list of [] -> [] hd :: tl ->

在Elm中,如何获取列表中的每个偶数索引并作为另一个列表返回?

所以您只想从列表中返回偶数索引项,对吗

下面是编写自己的函数的方法。我们将编写一个助手函数,
everySecond\uu
,如下所示

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)
此函数获取一个列表,以及一个表示该列表当前标题的索引的数字。我们需要将其作为参数传递给函数

然后我们在列表上进行模式匹配。如果是空的,我们返回一个空列表;这标志着递归的结束。列表中的最后一个元素始终是空列表。如果它不是一个空的列表,那么我们取头(第一个元素)和尾(一个表示向前的一切的列表)

如果我们的
索引
参数是偶数(
%2==0
表示“被二除时,不留余数”),我们希望保留此元素,因此我们将其附加到正在构建的列表的前面,并使用当前列表的尾部和递增的索引号再次调用
每隔一秒
继续构建

如果不是偶数,我们不想保留这个元素,所以我们只需返回
everySecond_utl(index+1)
,即列表的下一阶段,然后该过程重复

这就是它的逻辑。但这意味着我们需要调用
everySecond_uuo[foo,bar,baz]1
来使用我们的函数,始终将1作为默认参数传入。这不是直觉。这就是为什么我们用下划线称它为
everySecond\uuu
——这不是我们要让人们调用的,这是一个存在于幕后的助手函数。我们可以把它藏起来

everySecond : List a -> List a
everySecond list =
    everySecond_ list 1
现在你调用
everySecond[foo,bar,baz]
它工作得很好,基本上将起始索引默认为1


一种更简单的方法是根本不跟踪索引,而是使用布尔值(真/假)。你从一个False开始,而不是测试2的可除性,你只需要检查布尔值。如果为True,则保留该元素,并使用False再次调用该函数;如果为False,则忽略该元素并使用True再次调用该函数。

因此您希望仅返回列表中的索引项,对吗

下面是编写自己的函数的方法。我们将编写一个助手函数,
everySecond\uu
,如下所示

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)
此函数获取一个列表,以及一个表示该列表当前标题的索引的数字。我们需要将其作为参数传递给函数

然后我们在列表上进行模式匹配。如果是空的,我们返回一个空列表;这标志着递归的结束。列表中的最后一个元素始终是空列表。如果它不是一个空的列表,那么我们取头(第一个元素)和尾(一个表示向前的一切的列表)

如果我们的
索引
参数是偶数(
%2==0
表示“被二除时,不留余数”),我们希望保留此元素,因此我们将其附加到正在构建的列表的前面,并使用当前列表的尾部和递增的索引号再次调用
每隔一秒
继续构建

如果不是偶数,我们不想保留这个元素,所以我们只需返回
everySecond_utl(index+1)
,即列表的下一阶段,然后该过程重复

这就是它的逻辑。但这意味着我们需要调用
everySecond_uuo[foo,bar,baz]1
来使用我们的函数,始终将1作为默认参数传入。这不是直觉。这就是为什么我们用下划线称它为
everySecond\uuu
——这不是我们要让人们调用的,这是一个存在于幕后的助手函数。我们可以把它藏起来

everySecond : List a -> List a
everySecond list =
    everySecond_ list 1
现在你调用
everySecond[foo,bar,baz]
它工作得很好,基本上将起始索引默认为1


一种更简单的方法是根本不跟踪索引,而是使用布尔值(真/假)。你从一个False开始,而不是测试2的可除性,你只需要检查布尔值。如果为True,则保留该元素,并使用False再次调用该函数;如果为False,则忽略该元素并使用True再次调用该函数。

大多数情况下,您不需要编写递归函数,因为您可以使用标准的帮助器函数来实现这一点。以下是针对您的具体问题的解决方案:

takeEvenIndexes : List a -> List a
takeEvenIndexes l =
  l
  |> List.indexedMap (\ i x -> if i % 2 == 0 then Just x else Nothing)
  |> List.filterMap identity

该函数类似于
映射
,但也可以依赖于值的索引。和类似于一个映射,但您可以通过返回
Nothing
放弃一些值。在这里,它应用于函数,因为过滤已在前一行中预先计算。

大多数情况下,您不需要编程递归函数,因为您可以使用标准的辅助函数来为您编程。以下是针对您的具体问题的解决方案:

takeEvenIndexes : List a -> List a
takeEvenIndexes l =
  l
  |> List.indexedMap (\ i x -> if i % 2 == 0 then Just x else Nothing)
  |> List.filterMap identity

该函数类似于
映射
,但也可以依赖于值的索引。和类似于一个映射,但您可以通过返回
Nothing
放弃一些值。在这里,它被应用到函数中,因为过滤已经在前一行进行了预计算。

哇,函数编程比我想象的要困难得多。一开始看起来很难,也许做这样简单的事情更难。但这主要是一个让你的头脑围绕一个根本不同的方法的问题。一旦你有了一点练习,一切都开始点击——像这样的递归解决方案非常常见,所以你会习惯它们。不过,总的来说,这是一个不同的难度曲线:我觉得在函数式编程中,相对于命令式编程,简单的事情更难,而复杂的事情更容易。这是一个很好的折衷。哇,函数式编程