在haskell中按索引删除元素

qba*_*qba 11 haskell list

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

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

OOOOOXXXOOOOOXXX...
Run Code Online (Sandbox Code Playgroud)

我知道如何使用许多参数编写巨大的函数,但有没有聪明的方法来做到这一点?

Ste*_*202 16

两种完全不同的方法

  1. 您可以List.splitAtdrop:

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

    现在f [1..12]收益率[1,2,3,4,5,9,10,11,12].请注意,使用uncurry和可以更优雅地表达此功能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
    
    Run Code Online (Sandbox Code Playgroud)

    既然我们正在使用Control.Arrow,我们可以选择放弃splitAt,而是在帮助下打电话Control.Arrow.(&&&),并结合take:

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

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

    f :: [a] -> [a] 
    f [] = []
    f xs = take 5 xs ++ (f . drop 8) xs
    
    Run Code Online (Sandbox Code Playgroud)

    正如Chris Lutz所说,这个解决方案可以概括如下:

    nofm :: Int -> Int -> [a] -> [a]
    nofm _ _ [] = []
    nofm n m xs = take n xs ++ (nofm n m . drop m) xs
    
    Run Code Online (Sandbox Code Playgroud)

    现在nofm 5 8产生所需的功能.请注意,解决方案splitAt可能仍然更有效!

  2. 应用数学的一些使用map,snd,filter,modzip:

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

    这里的想法是我们将列表中的每个元素与其索引(自然数i)配对.然后我们删除那些i%8> 4的元素.此解决方案的一般版本是:

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


小智 9

这是我的看法:

deleteAt idx xs = lft ++ rgt
  where (lft, (_:rgt)) = splitAt idx xs
Run Code Online (Sandbox Code Playgroud)


dot*_*mag 5

您可以轻松计算元素:

strip' (x:xs) n | n == 7 = strip' xs 0
                | n >= 5 = strip' xs (n+1)
                | n < 5 = x : strip' xs (n+1)
strip l = strip' l 0
Run Code Online (Sandbox Code Playgroud)

尽管开放式编码看起来更短:

strip (a:b:c:d:e:_:_:_:xs) = a:b:c:d:e:strip xs
strip (a:b:c:d:e:xs) = a:b:c:d:e:[]
strip xs = xs
Run Code Online (Sandbox Code Playgroud)


ADE*_*Ept 5

由于没有人制作带有“unfoldr”的版本,这是我的看法:

drop3after5 lst = concat $ unfoldr chunk lst
  where
    chunk [] = Nothing
    chunk lst = Just (take 5 lst, drop (5+3) lst)
Run Code Online (Sandbox Code Playgroud)

貌似是迄今为止最短的