从 Haskell 中的列表中删除特定元素

Removing specific elements from lists in Haskell

我很难将 Haskell 和函数式编程放在一起。我想要做的是操纵一个字符串,以便我每次根据给定的数字成为 printing/returning 个特定字符。例如:

printing "testing" 2 = "etn"

printing "testing" 3 = "sn"

我在网上看了很多,据我所知,我可以通过过滤和循环来实现这一点,但我无法get/understand这种语言的语法来获得一个工作程序。

我将尝试描述我的思考过程,以便您了解。此函数符合通过重复函数应用(此处删除一些元素)从输入种子(此处为字符串)创建输出列表(此处为字符串)的模式。因此我选择了 Data.List.unfoldr.

的实现
unfoldr :: (b -> Maybe (a, b)) -> b -> [a]

好的,我需要将种子 b 变成 (Maybe) 输出 a 和字符串的其余部分。我将调用此子函数 f 并将其传递给 unfoldr.

printing s n = unfoldr f s
  where f b = case drop n b of
                [] -> Nothing
                (x:xs) -> Just (x,xs)

事实证明,尝试从列表的前面取出头部并返回 Maybe 也是一种常见的模式。是 Data.List.uncons,所以

printing s n = unfoldr (uncons . drop n) s

很流畅!所以我测试了一下,输出是错误的!您指定的输出实际上例如。 for n=2 选择每第二个字符,即。掉落 (n-1) 个字符。

printing s n = unfoldr (uncons . drop (n-1)) s

我再次测试它,它符合所需的输出。呸!

为了演示 Haskell 语言,一些已接受答案的替代解决方案。

使用列表理解

printing :: Int -> String -> String
printing j ls = [s | (i, s) <- zip [1 .. ] ls, mod i j == 0]

使用递归:

printing' :: Int -> String -> String 
printing' n ls 
    | null ls'    = []
    | otherwise   = x : printing' n xs
    where
    ls'         = drop (n - 1) ls
    (x : xs)    = ls' 

在这两种情况下,我都翻转了参数,因此更容易进行部分应用:例如,printing 5 是一个新函数,在应用于字符串时会给出每个第 5 个字符。

请注意,稍作修改后它们将适用于任何列表

takeEvery :: Int -> [a] -> [a]