问题描述
我是haskell的新成员,我正在寻找一些标准函数来处理索引列表。
我确切的问题是,我想在每5次后删除3个元素。如果它不够清晰,这里是插图:
OOOOOXXXOOOOOXXX ...
我知道如何用很多参数编写巨大的函数,但是有没有什么聪明的方法可以做到这一点?
解决方案我是haskell的新成员,我正在寻找一些标准函数来处理索引列表。
我确切的问题是,我想在每5次后删除3个元素。如果它不够清晰,这里是插图:
OOOOOXXXOOOOOXXX ...
我知道如何用很多参数编写巨大的函数,但是有没有什么聪明的方法可以做到这一点?
解决方案
您可以使用与 :
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]
。请注意,此功能可以使用和:
import Data.List(splitAt)
import Control.Arrow(second)
f :: [a] - > [a]
f [] = []
f xs = uncurry(++)$ second(f。drop 3)$ splitAt 5 xs
因为我们使用无论如何,我们可以选择放弃 splitAt
而是在与:
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
正如指出的那样,这个解决方案可以概括如下:
nofm :: Int - > Int - > [a] - > [a]
nofm _ _ [] = []
nofm nm xs = take n xs ++(nofm nm。drop m)xs
现在 nofm 5 8
产生所需的函数。请注意,使用 splitAt
的解决方案可能仍然更有效率!
应用一些数学运用,,,和:
f :: [a] - > [a]
f = map snd。过滤器(\(i,_) - > i`mod` 8
这里的想法是我们将列表中的每个元素与它的索引,自然数 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?
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!
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中的索引删除元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!