Remove first instance x from list

I am new to Haskell and trying to find the basics.

Suppose I have the following list y:

3:3:2:1:9:7:3:[]

I am trying to find a way to remove the first occurrence of 3 in the list y. Is this possible with a simple list comprehension?

What I tried (this method removes all instances from the list):

 deleteFirst _ [] = [] deleteFirst a (b:bc) | a == b = deleteFirst a bc | otherwise = b : deleteFirst a bc 
+2
source share
4 answers

since another understanding of the list already mentioned is not a suitable solution for this task (it is difficult to complete the execution in one step).

You almost wrote the correct solution, only in case of equality with the agreed value, you had to complete the calculation by returning the remaining list without the agreed element:

 deleteFirst _ [] = [] deleteFirst a (b:bc) | a == b = bc | otherwise = b : deleteFirst a bc > print $ deleteFirst 3 (3:3:2:1:9:7:3:[]) > [3,2,1,9,7,3] 
+3
source

No, this is not possible using list comprehension. In understanding the list, you decide which item should be stored only on that item. In your example, you want to handle the first 3s that you encounter differently than the other 3s (because you want to remove only the first), so the solution does not depend only on the element. Thus, a list comprehension will not work.

Your attempt using a recursive function is already pretty close, except that, as you said, deletes all instances. Why does he delete all instances? Because after you delete the first one, you again call deleteFirst in the rest of the list, which will delete the next instance and so on. To fix this, simply do not call deleteFirst again after deleting the first instance. So just use bc instead of deleteFirst a bc in this case.

+6
source

I do not believe that it is possible to do this with a list (at least not in any idiomatic way).

Your deleteFirst works almost. All you need to change to fix is ​​to stop deleting after the first match, i.e. Replace deleteFirst a bc in the first sentence with bc .

+2
source

sepp2k remarks on concept lists is an important thing to understand; such as map , filter , foldr , etc., process all elements of the list evenly, and it is important to understand what information is available at each step, and how the result of each step is combined with other steps.

But the aspect that I want to emphasize is that I think that you really should try to solve these problems in terms of library functions. Adapting the solution from this older answer of mine to your problem:

 deleteFirst x xs = beforeX ++ afterX -- Split the list into two pieces: -- * prefix = all items before first x -- * suffix = all items after first x where (beforeX, xAndLater) = break (/=x) xs afterX = case xAndLater of [] -> [] (_:xs) -> xs 

The trick is that break already has built-in "before the first hit" behavior. As an additional exercise, you can try writing your own version of break ; learning to write these small, general, and reusable functions is always useful.

0
source

All Articles