从字符串中删除每个第n个元素

时间:2011-03-13 11:15:38

标签: haskell

如何删除字符串的每个第n个元素?

我猜你会以某种方式使用drop函数。

就像这样丢弃第一个n,你怎么能改变这个,所以只丢下第n个,然后是第n个,等等,而不是全部?

dropthem n xs = drop n xs

5 个答案:

答案 0 :(得分:9)

简单。取(n-1)个元素,然后跳过1,冲洗并重复。

dropEvery _ [] = []
dropEvery n xs = take (n-1) xs ++ dropEvery n (drop n xs)

或者为了效率而以showS风格

dropEvery n xs = dropEvery' n xs $ []
    where dropEvery' n [] = id
          dropEvery' n xs = (take (n-1) xs ++) . dropEvery n (drop n xs)

答案 1 :(得分:5)

-- groups is a pretty useful function on its own!
groups :: Int -> [a] -> [[a]]
groups n = map (take n) . takeWhile (not . null) . iterate (drop n)

removeEveryNth :: Int -> [a] -> [a]
removeEveryNth n = concatMap (take (n-1)) . groups n

答案 2 :(得分:3)

remove_every_nth :: Int -> [a] -> [a]
remove_every_nth n = foldr step [] . zip [1..]
    where step (i,x) acc = if (i `mod` n) == 0 then acc else x:acc

这是函数的作用:

zip [1..]用于索引列表中的所有项目,例如zip [1..] "foo"变为[(1,'f'), (2,'o'), (3,'o')]

然后使用right fold处理索引列表,该{{3}}累积其索引不能被n整除的每个元素。

这是一个稍微长一点的版本,基本上做同样的事情,但避免了来自zip [1..]的额外内存分配,并且不需要计算模数。

remove_every_nth :: Int -> [a] -> [a]
remove_every_nth = recur 1
    where recur _ _ []     = []
          recur i n (x:xs) = if i == n
            then recur 1 n xs
            else x:recur (i+1) n xs

答案 3 :(得分:2)

尝试合并takedrop来实现这一目标。

take 3 "hello world" = "hel"
drop 4 "hello world" = "o world"

答案 4 :(得分:2)

我喜欢以下解决方案:

del_every_nth :: Int -> [a] -> [a]    
del_every_nth n = concat . map init . group n 

您只需要定义一个函数group,它将长度为n的部分分组。但这很容易:

group :: Int -> [a] -> [[a]]
group n [] = []
group n xs = take n xs : group n (drop n xs)