Haskell - Filter Last Element

后端 未结 4 1472
北荒
北荒 2021-01-18 17:36

I want to filter the last element of a list that does not satisfy a property. An example would be

smallerOne :: a->Bool 
smallerOne x = x < 1 
         


        
4条回答
  •  滥情空心
    2021-01-18 18:10

    What you want to do is reverse the list and take elements while they dont satisfy the property. The moment an element satisfies a property, you drop it and take the rest of the list. This translates pretty naturally into haskell code.

    filterLast :: (a -> Bool) -> [a] -> [a]
    filterLast p = reverse . uncurry (++) . dropHeadSnd . span p . reverse
      where
        dropHeadSnd (x, y) = (x, tail' y)
        tail' [] = []
        tail' (x:xs) = xs
    

    The (++) reduces the efficiency of your code and while its not the asymptotic efficiency, eliminating the (++) will improve your performance.

    filterLast :: (a -> Bool) -> [a] -> [a]
    filterLast p = reverse . helper . reverse
      where
        helper [] = [] 
        helper (x:xs) | p x = xs
                      | otherwise = x:helper xs
    

    Both of the above functions use two iterations over the list. However remember with recursion you can get information from both behind and ahead. We use the recursive call to figure out if there are any subsequent elements for which 'p' is satisfied.

    f :: (a -> Bool) -> [a] -> [a]
    f p = snd . helper 
     where
       helper [] = (False, [])
       helper (a:as) | p a && flag = (flag, a:as')
                     | p a = (True, as')
                     | otherwise = (flag, a:as')
              where
               (flag, as') = helper as
    

提交回复
热议问题