gpt4 book ai didi

list - 编辑列表中的每个第 N 个项目

转载 作者:行者123 更新时间:2023-12-02 02:48:55 24 4
gpt4 key购买 nike

我想对整数列表执行算术运算(例如将值加倍),每 n 个位置。

例如,给定列表 [1,2,3,4,5,6,7] ,我想每三个地方加倍值。在那种情况下,我们会有 [1,2,6,4,5,12,7] .

我该怎么做?

最佳答案

applyEvery :: Int -> (a -> a) -> [a] -> [a]
applyEvery n f = zipWith ($) (cycle (replicate (n-1) id ++ [f]))
cycle subexpression 构建函数列表 [id,id,...,id,f]使用正确数量的元素并令人作呕地重复它,而 zipWith ($)将该函数列表应用于参数列表。

既然你问了,那就更详细了!随时要求更多解释。

主要思想可能最好用 ASCII 图片来解释(这不会阻止我写一千个 ASCII 字!):
functions : [ id, id, f  , id, id, f  , id, id, f, ... 
input list: [ 1, 2, 3, 4, 5, 6, 7 ]
-----------------------------------------------------
result : [ 1, 2, f 3, 4, 5, f 6, 7 ]

就像没有理由硬编码您希望列表中每三个元素加倍一样, f 也没有什么特别之处。 (在您的示例中是加倍),除了它应该与什么都不做具有相同的结果类型。所以我把这些作为我的函数的参数。对数字列表进行操作甚至并不重要,因此该函数适用于 a 列表。 ,只要给它一个“间隔”和一个操作。这给了我们类型签名 applyEvery :: Int -> (a -> a) -> [a] -> [a] .我把输入列表放在最后,因为然后是像 doubleEveryThird = applyEvery 3 (*2) 这样的部分应用程序是返回一个新列表的东西,一个所谓的组合器。我基本上随机选择了其他两个参数的顺序:-)

为了构建函数列表,我们首先组装基本构建块,由 n-1 id 组成。 s,后跟 f如下: replicate (n-1) id ++ [f] . replicate m x制作一个包含 m 的列表 x 的重复论证,例如 replicate 5 'a' = "aaaaa" ,但它也适用于函数。我们必须附加 f包裹在它自己的列表中,而不是使用 :因为您只能在前面添加单个元素 - Haskell 的列表是单链接的。

接下来,我们继续使用 cycle 重复基本构建块(不是 repeat,因为我第一次错误地)。 cycle有类型 [a] -> [a]所以结果是一个“相同级别的嵌套”的列表。示例 cycle [1,2,3]计算结果为 [1,2,3,1,2,3,1,2,3,...]
[旁注:我们唯一没有使用过的repeat-y函数是 repeat本身:形成一个由其参数组成的无限列表]

有了这个,稍微有点棘手的 zipWith ($)部分。您可能已经知道普通 zip函数,它接受两个列表并将元素放在结果中元组的同一位置,当任一列表用完元素时终止。如图:
    xs   : [ a  , b    , c   , d, e] 
ys: [ x, y , z ]
------------------------------
zip xs ys: [(a,x),(b,y),(c,z)]

这已经很像第一张照片了,对吧?唯一的事情是我们不想将单个元素放在一个元组中,而是将第一个元素(它是一个函数)应用于第二个元素。使用自定义组合功能进行压缩是通过 zipWith 完成的.另一张照片(最后一张,我保证!):
          xs   : [   a  ,   b  ,   c   , d, e] 
ys: [ x, y, z ]
----------------------------------------
zipWith f xs ys: [ f a x, f b y, f c z ]

现在,我们应该选择什么 zipWith和?好吧,我们想将第一个参数应用于第二个参数,所以 (\f x -> f x)应该做的伎俩。如果 lambdas 让你不舒服,你也可以定义一个顶级函数 apply f x = f x并使用它。但是,这已经是 Prelude 中的标准运算符,即 $ !由于您不能将中缀运算符用作独立函数,因此我们必须使用语法糖 ($) (这实际上只是意味着 (\f x -> f $ x) )

将以上所有内容放在一起,我们得到:
applyEvery :: Int -> (a -> a) -> [a] -> [a]
applyEvery n f xs = zipWith ($) (cycle (replicate (n-1) id ++ [f])) xs

但是我们可以去掉 xs最后,导致我给出的定义。

关于list - 编辑列表中的每个第 N 个项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35752255/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com