创建输入列表的第N个元素的列表

时间:2014-09-18 16:56:05

标签: haskell

当我不熟悉Haskell时,请耐心等待。

我试图写一个输出的函数:

  

输出中的第一个列表应与输入列表相同。该   输出中的第二个列表应包含来自的每个第二个元素   输入列表等。

示例:func "ABCD" = ["ABCD","BD","C","D"]

我开始编写一个函数来获取列表的每个第n个元素:

everyN n xs = case drop (n-1) xs of
                [] -> []
                (z:zs) -> z : everyN n zs

现在我知道我只需要一个调用此函数的函数,并在每次调用时递增n值,但我不能考虑如何编写这样的功能或者表达它的最简洁的方式。如果可能的话,我不想使用显式递归并使用haskell语言函数。

有人能指出我正确的方向吗?

1 个答案:

答案 0 :(得分:4)

我知道这有点蹩脚,因为@chi已经给你发表了评论 - 但也许作为奖励,我有一个替代你的everyN

everyN :: Int -> [a] -> [a]
everyN n xs = every n xs
  where every _ [] = []
        every 1 (x:xs) = x : every n xs
        every m (_:xs) = every (m-1) xs

seqN :: [a] -> [[a]]
seqN xs = [ everyN n xs | n <- [1..length xs] ]

这是使用地图相同(再次提到@chi):

seqN' :: [a] -> [[a]]
seqN' xs = map (flip everyN xs) [1..length xs]

解释

有人让我解释一下:

首先看地图:map :: (a -> b) -> [a] -> [b] - 现在显然我们想要适应everyNeveryN两个参数我们肯定想要部分应用它某事。正在更改的参数不是输入列表xs,而n - xs将保持不变。

所以我们肯定要将everyN部分应用于xs - 但我们不能,因为这个论点是错误的。

flip救援:此翻转 everyN的参数:

flip everyN :: [a] -> Int -> [a]

我们可以将此部分应用于xs并写入:

flip everyN xs :: Int -> [a]

最后我们可以将map用于n(当然1 .. length xs超过length xs - 因为如果我们跳转的时间超过{{1}},则无需选择任何内容)如图所示。

如何把这个放入一个我不知道的英语句子中;)