Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delete Second Occurence of Element in List - Haskell

Tags:

list

haskell

I'm trying to write a function that deletes the second occurrence of an element in a list. Currently, I've written a function that removes the first element:

    removeFirst _ [] = [] 
    removeFirst a (x:xs) | a == x    = xs
                          | otherwise = x : removeFirst a xs

as a starting point. However,I'm not sure this function can be accomplished with list comprehension. Is there a way to implement this using map?

EDIT: Now I have added a removeSecond function which calls the first

    deleteSecond :: Eq a => a -> [a] -> [a]
    deleteSecond _ [] = []
    deleteSecond a (x:xs) | x==a = removeFirst a xs
                  | otherwise = x:removeSecond a xs

However now the list that is returned removes the first AND second occurrence of an element.

like image 624
user3476396 Avatar asked Mar 30 '14 00:03

user3476396


People also ask

How do you delete an element in a list in Haskell?

You first compare the head of the list ( y ) to the item you want to remove and correctly return the item or an empty list using areTheySame . Then you want to recursively continue using removeItem on the rest of the list ( ys ). The resulting list needs to be concatenated using ++ .

How do you remove the nth element from a list in Haskell?

Haskell is statically typed, and every function or variable has a type. In this case, removeNth is a function that takes an integer (the position n ) and a list of any type as its argument and returns a list with the nth element removed.

How do you get the first N elements of a list in Haskell?

There is a function in Haskell that takes first n elements of user-supplied list, named take . The syntax is: function-name arg1 arg2 . So, take takes first 1000 elements from an infinite list of numbers from 0 to infinity.


2 Answers

Well, assuming you've got removeFirst - how about searching for the first occurence, and then using removeFirst on the remaining list?

removeSecond :: Eq a => a -> [a] -> [a]
removeSecond _ [] = []
removeSecond a (x:xs) | x==a = x:removeFirst a xs
                      | otherwise = x:removeSecond a xs
like image 130
Benesh Avatar answered Oct 07 '22 07:10

Benesh


You could also implement this as a fold.

removeNth :: Eq a => Int -> a -> [a] -> [a]
removeNth n a = concatMap snd . scanl go (0,[])
  where go (m,_) b | a /= b    = (m,   [b])
                   | n /= m    = (m+1, [b])
                   | otherwise = (m+1, [])

and in action:

λ removeNth 0 1 [1,2,3,1]
[2,3,1]
λ removeNth 1 1 [1,2,3,1]
[1,2,3]

I used scanl rather than foldl or foldr so it could both pass state left-to-right and work on infinite lists:

λ take 11 . removeNth 3 'a' $ cycle "abc"
"abcabcabcbc"
like image 30
rampion Avatar answered Oct 07 '22 09:10

rampion