Home > OS >  Haskell - Remove n smallest elements in a list of tuples
Haskell - Remove n smallest elements in a list of tuples

Time:12-16

I've got the following code that takes an int value and removes the first n amount of elements in a list.

removeEle :: Int -> [a] -> [a]
removeEle n xs
    | ((n <= 0) || null xs) = xs
    | otherwise = removeEle (n-1) (tail xs)

How would i append this so that this works on a list of tuples by their second element? etc

[(String1, 50)], [(String2, 600)], [(String3, 10)]

CodePudding user response:

There is not much you can do to amend your current solution so that it removes the first n smallest elements. To be able to remove the first n smallest, you need to have the total ordering of the whole list so that you can decide which elements are in the n smallest interval.

One easy solution is to sort the list and the remove the first n elements. This solution doesn't preserve the original ordering though.

Using soryBy and drop from Data.List you can do the following:

removeNSmallest :: Ord a => Int -> [(String, a)] -> [(String, a)]
removeNSmallest n xs = drop n $ sortBy (\(_, a) (_, b) -> compare a b) xs

As @Micha Wiedenmann pointed out, you can use sortBy (comparing snd) for sorting the tuples.

A small test:

λ> removeNSmallest 1 [("String1", 50), ("String2", 600), ("String3", 10)]
[("String1",50),("String2",600)]

To preserve the original ordering, one solution is to create a separate ordered list of the second elements of the tuple. Then traverse the original list and for each element that is in the ordered list, remove one from the original.

Your original solution for removing the first n elements of a list would be much more readable if you wrote it using drop:

removeEle :: Int -> [a] -> [a]
removeEle n xs = drop n xs

Or if you want to use explicit recursion:

removeEle :: Int -> [a] -> [a]
removeEle _ [] = []
removeEle 0 xs = xs
removeEle n x:xs = removeEle (n-1) xs
  • Related