通过haskell中的索引删除元素 [英] Remove elements by index in haskell

查看:165
本文介绍了通过haskell中的索引删除元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是haskell的新成员,我正在寻找一些标准函数来处理索引列表。



我确切的问题是,我想在每5次后删除3个元素。如果它不够清晰,这里是插图:

  OOOOOXXXOOOOOXXX ... 

我知道如何用很多参数编写巨大的函数,但是有没有什么聪明的方法可以做到这一点?

解决方案

两种完全不同的方法




  1. 您可以使用 List.splitAt drop

      import Data.List(splitAt)
    f :: [a] - > [a]
    f [] = []
    f xs = let(h,t)= splitAt 5 xs in h ++ f(drop 3 t)

    现在 f [1..12] 产生 [1,2, 3,4,5,9,10,11,12] 。请注意,此功能可以使用 uncurry
    $ {code> Control.Arrow.second

      import Data.List(splitAt)
    import Control.Arrow(second)
    f :: [a] - > [a]
    f [] = []
    f xs = uncurry(++)$ second(f。drop 3)$ splitAt 5 xs

    因为我们使用 Control.Arrow 无论如何,我们可以选择放弃 splitAt 而是在 Control.Arrow。(&&) take

      import Control.Arrow((&&& amp;& amp; amp; amp;))
    f :: [a] - > [a]
    f [] = []
    f xs = uncurry(++)$(以5&&(f。drop 8))xs

    但是现在很明显,更简短的解决方案如下:

      f :: [a]  - > [a] 
    f [] = []
    f xs = take 5 xs ++(f。drop 8)xs

    正如 Chris Lutz 指出的那样,这个解决方案可以概括如下:

      nofm :: Int  - > Int  - > [a]  - > [a] 
    nofm _ _ [] = []
    nofm nm xs = take n xs ++(nofm nm。drop m)xs

    现在 nofm 5 8 产生所需的函数。请注意,使用 splitAt 的解决方案可能仍然更有效率!


  2. 应用一些数学运用 map snd filter mod zip

      f :: [a]  - > [a] 
    f = map snd。过滤器(\(i,_) - > i`mod` 8 <(5 :: Int))。 zip [0 ..]

    这里的想法是我们将列表中的每个元素与它的索引,自然数 i 。然后我们删除那些 i%8> 4 的元素。该解决方案的通用版本是:

      nofm :: Int  - > Int  - > [a]  - > [a] 
    nofm n m = map snd。过滤器(\(i,_)→i`mod` m



I'm new in haskell and I'm looking for some standard functions to work with lists by indexes.

My exact problem is that i want to remove 3 elements after every 5. If its not clear enough here is illustration:

OOOOOXXXOOOOOXXX...

I know how to write huge function with many parameters, but is there any clever way to do this?

解决方案

Two completely different approaches

  1. You can use List.splitAt together with drop:

    import Data.List (splitAt)
    f :: [a] -> [a]
    f [] = []
    f xs = let (h, t) = splitAt 5 xs in h ++ f (drop 3 t)
    

    Now f [1..12] yields [1,2,3,4,5,9,10,11,12]. Note that this function can be expressed more elegantly using uncurry and Control.Arrow.second:

    import Data.List (splitAt)
    import Control.Arrow (second)
    f :: [a] -> [a]
    f [] = []
    f xs = uncurry (++) $ second (f . drop 3) $ splitAt 5 xs
    

    Since we're using Control.Arrow anyway, we can opt to drop splitAt and instead call in the help of Control.Arrow.(&&&), combined with take:

    import Control.Arrow ((&&&))
    f :: [a] -> [a]
    f [] = []
    f xs = uncurry (++) $ (take 5 &&& (f . drop 8)) xs
    

    But now it's clear that an even shorter solution is the following:

    f :: [a] -> [a] 
    f [] = []
    f xs = take 5 xs ++ (f . drop 8) xs
    

    As Chris Lutz notes, this solution can then be generalized as follows:

    nofm :: Int -> Int -> [a] -> [a]
    nofm _ _ [] = []
    nofm n m xs = take n xs ++ (nofm n m . drop m) xs
    

    Now nofm 5 8 yields the required function. Note that a solution with splitAt may still be more efficient!

  2. Apply some mathematics using map, snd, filter, mod and zip:

    f :: [a] -> [a]
    f = map snd . filter (\(i, _) -> i `mod` 8 < (5 :: Int)) . zip [0..]
    

    The idea here is that we pair each element in the list with its index, a natural number i. We then remove those elements for which i % 8 > 4. The general version of this solution is:

    nofm :: Int -> Int -> [a] -> [a]
    nofm n m = map snd . filter (\(i, _) -> i `mod` m < n) . zip [0..]
    

这篇关于通过haskell中的索引删除元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆