I am trying to delete consecutive duplicates in a list; for instance, given the list [1,2,2,3,4], it the function I need must return [1,3,4].
My code at the end of the question, however, doesn't work if trailing duplicates are in list, like in [1,2,3,4,4].
I also want to do it in as simple terms as possible, how can I do this?
myCom :: Eq a => [a] -> [a]
myCom (x:y:ys#(z:_))
| x == y = myCom ys
| otherwise = x : myCom (y:ys)
myCom ys = ys
The first pattern match you have only catches lists with at least 3 elements.
That is why when the duplicates are at the end of the list when
myCom [4,4]
is called it simply uses
myCom ys = ys
and returns itself. You can catch this by defining myCom for lists with at least 2 elements as below (you werent't using z anyway):
myCom (x:y:ys)
| x == y = myCom ys
| otherwise = x : myCom (y:ys)
myCom ys = ys
This gives
myCom [1,2,2,3,4,4] = [1,3]
There is still an issue with 3 (an odd number) consecutive numbers. For example we get:
myCom [1,2,2,2] = [1,2]
but I understand that this is desired behavior.
I would use Maybe to represent a length of one as a success condition. This works well with Haskell's pattern-matching syntax. You can then use group (from Data.List) and filter out the Nothings using catMaybe (from Data.Maybe) :
myCom = catMaybes . map lenOne . group
where lenOne [x] = Just x
lenOne _ = Nothing
From a comment I see that the function Data.Set.nub just does what the OP asks.
However, my first attempt to solve the problem was the following, which only removes duplicates if they are consecutive (e.g. [1,2,1,2,1,2] is not changed):
concat $ filter (\x -> length x == 1) $ Data.List.group [1,2,3,4,4]
I hope this answer could be useful to some random user ending up on this page.
Related
(I am currently doing an online course on Haskell and this is an exercise. I am not looking for answers, but simply for some pointers on how to proceed!)
I have trouble wrapping my head around this. In imperative languages I would simply use a loop, but since Haskell doesn't really have those I am left scratching my head.
I need to write a function nextIsGreater :: [Int] -> [Int] that, given a list of numbers, produces a list with all elements of the input list such that the element is followed by a greater number in the input list (the next number is greater).
Here is what I've managed to come up with so far.
nextIsGreater :: [Int] -> [Int]
nextIsGreater xs = [x | x <- init xs, y <- tail xs, x < y]
So far it works if I have only two numbers in the list. Say [0,5], it returns [0] as it is supposed to. If I have, say [0,5,6] then my code seems to check the 0 against both of the next numbers in the list and returns [0,0,5], when it should return [0,5]. How could I compare each adjacent number to eachother?
Not a bad attempt, but
[x | x <- init xs, y <- tail xs, x < y]
corresponds to a nested loop: you choose x from init xs, and then for each of these choices you pick all possible y from tail xs.
To make the idea work as intended, you'd need to use {-# LANGUAGE ParallelListComp #-} or equivalently zip the sources:
nextIsGreater xs = [x | (x,y) <- zip (init xs) (tail xs), x<y]
But there's a simpler way to obtain all choices of two consecutive elements, with tails:
nextIsGreater xs = [x | (x:y:_) <- tails xs, x<y]
The intention of this exercise is almost certainly to have you write a standard recursive solution using pattern matching, not use list comprehensions or higher level functions or anything like that.
If the course is any good, you should already have covered some recursive list-to-list transformations, functions with definitions of the form:
foo :: [Int] -> [Int]
foo (x:xs) = ... something involving "x" and "foo xs" ...
foo [] = ...
or similar, and you're expected to write something along the same lines.
Here's a first hint, with further spoilers below.
A simple way of writing a recursive function that operates on adjacent elements of lists is to write a pattern that names the first two elements:
foo (x:y:zs) = ...
The "..." can operate on x and y, and then perform a recursive call to process the "rest" of the list. The recursive call might be either foo zs or foo (y:zs) (or switch between those based on some condition), depending on what the function is doing.
Because this pattern will only match lists with at least two elements, you will usually also need patterns to match both one-element and empty lists:
foo [x] = ...
foo [] = ...
If that's not clear enough, let me refresh your memory on basic recursive list-to-list transformations starting with an example that doesn't inspect adjacent elements.
SPOILERS
.
.
.
Suppose we want to filter out all even elements from a list. A recursive solution would consider the two cases:
evens (x:xs) = ...
evens [] = ...
For the first case, the extraction of all evens from x:xs either includes x plus all the evens from xs (i.e., evens xs) or excludes x and includes only evens xs, depending on whether or not x itself even:
evens (x:xs) | even x = ...
| otherwise = ...
In particular, if x is even, the answer should include x together with evens xs:
evens (x:xs) | even x = x : evens xs
and if x is odd, the answer just should include evens xs:
| otherwise = evens xs
The final case is the subset of even numbers from the empty list, which is just the empty list:
evens [] = []
giving the complete definition:
evens :: [Int] -> [Int]
evens (x:xs) | even x = x : evens xs
| otherwise = evens xs
evens [] = []
The main difference in your example is that the decision to include x depends not only on x but on the element appearing after x, so let's consider a slightly different problem: take a list and output all elements that are followed by an even number.
We might consider starting with a similar structure:
beforeEvens (x:xs) | ... = x : beforeEvens xs -- include x
| otherwise = beforeEvens xs -- exclude x
beforeEvens [] = []
where "..." checks to see if the element after x (i.e., the first element of xs) is even. For example, we might call a separate function to check this:
beforeEvens (x:xs) | headIsEven xs = x : beforeEvens xs
| otherwise = beforeEvens xs
beforeEvens [] = []
You ought to be able to write a decent definition of headIsEven to complete this. Bonus points if instead of using head, it uses pattern matching. Note the special case headIsEven [] should return False.
A more direct approach, though, is to take advantage of the fact that patterns can be used to examine multiple elements at the start of the list. Here, we match a pattern that names the first two elements x and y, plus the rest of the list zs:
beforeEvens (x:y:zs) | even y = x : beforeEvens (y:zs)
| otherwise = beforeEvens (y:zs)
beforeEvens [x] = []
beforeEvens [] = []
Note a couple of tricky points here. If we match against the pattern (x:y:zs), then we have to be careful about whether we recurse on y:zs or zs alone. It depends on whether y should or shouldn't be considered for inclusion in the output. Also, the pattern (x:y:zs) won't match a singleton list, so we need an extra pattern match on that.
Because the last two cases are the same, we can combine them into a single case:
beforeEvens (x:y:zs) | even y = x : beforeEvens (y:zs)
| otherwise = beforeEvens (y:zs)
beforeEvens _ = []
You should find it relatively straightforward to modify beforeEvens to write your nextIsGreater function.
I tried with something like this but it doesn't work how I wanted it to do. I'm new kinda new to Haskell, and I don't really know how to do it, and what's wrong.
insert a (x:xs) = insert2 a (x:xs) []
where insert2 el (x:xs) hd =
if (x:xs) == []
then []
else if ( a>=x && a < head(xs))
then hd ++ [x] ++ [a] ++ xs
else insert2 a xs hd++[x]
main = do
let list =[1 ,2 ,3 ,4 ,5 ,6]
let out = insert 2 list
print out
The output I get is [2,2,3,4,5,6,1]
First a couple of cosmetics:
Ensure indentation is right. When copy/pasting into StackOverflow, it's generally best to use ctrl+k to get it in code-block style.
There's no point matching (x:xs) only to pass the entire thing into your local function.
Omit unnecessary parentheses and use standardised spacing.
With that, your code becomes
insert a allxs = insert2 a allxs []
where insert2 el (x:xs) hd =
if x:xs == []
then []
else if a >= x && a < head xs
then hd ++ [x] ++ [a] ++ xs
else insert2 a xs hd ++ [x]
main = do
let list = [1, 2, 3, 4, 5, 6]
let out = insert 2 list
print out
Algorithmically speaking, there's no point in using an “accumulator argument” here. It's easier and actually more efficient to directly recurse on the input, and simply pass on the remaining tail after done with the insertion. Also remember to have a base case:
insert a [] = [a]
insert a (x:xs) = ...
You also don't need to use head. You've already pattern-matched the head element with the x:xs pattern. If you did need another list element, you should match that right there too, like
insert a (x:x':xs) = ...
...but you don't in fact need that, x is enough to determine what to do. Namely,
insert a (x:xs)
| a<=x = -- if the list was ordered, this implies that now _all_
-- its elements must be greater or equal a. Do you
-- need any recursion anymore?
| otherwise = -- ok, `x` was smaller, so you need to insert after it.
-- Recursion is needed here.
Here are some hints. It's a lot simpler than you're making it. You definitely don't need a helper function.
insert a [] = ??
insert a (x : xs)
| a <= x = ???
| otherwise = ???
Two things:
Prepending to a list is more efficient than appending to one.
Haskell lets you write separate definitions to avoid having to write single, nested conditional expressions.
There are two kinds of list you can insert into: empty and non-empty. Each can be handled by a separate definition, which the compiler will use to define a single function.
insert a [] = [a]
insert a (x:xs) = ...
The first case is easy: inserting into an empty list produces a singleton list. The second case is tricker: what you do depends on whether a is smaller than x or not. You can use a conditional expression
insert a (x:xs) = if a < x then a : insert x xs else x : insert a xs
thought you may see guards used instead:
insert a (x:xs) | a < x = a : insert x xs
| otherwise = x : insert a xs
In both cases, we know (because the list argument is already sorted) that insert x xs == x : xs, so we can write that directly to "short-circuit" the recursion:
insert a (x:xs) = if a < x then a : x : xs else x : insert a xs
don't complicate! , make simple ...
insertme a list = takeWhile (<a) list ++ [a] ++ dropWhile (<a) list
I have a big list of lists. And I want to concat every third list into each other. Like such
let xss = [[1,2,3],[1,2,3],[1,2,3],
[4,5,6],[4,5,6],[4,5,6],
[7,8,9],[7,8,9],[7,8,9]]
someFunk xss = [[1,2,3,1,2,3,1,2,3],
[4,5,6,4,5,6,4,5,6],
[7,8,9,7,8,9,7,8,9]]
Is there a way of doing this?
Just for bikeshedding purposes, I think I would write something like this:
import Data.List.Split
someFunk = map concat . chunksOf 3
It's concise, and I think it also reads a lot like your English description. It uses the split package.
You could try something like this:
someFunk :: [[a]] -> [[a]]
someFunk (x:y:z:zs) = (x ++ y ++ z) : someFunk zs
someFunk (x:y:ys) = (x ++ y) : someFunk ys
someFunk (x:xs) = x : someFunk xs
someFunk _ = []
Using pattern matching, you check for a list with at least three lists, join them and recursively call it on the remainder of the list. If the list count is not an exact multiple of 3, the subsequent patterns still allow you to concatenate the next 3 while available.
Demo
I'm looking for a cleaner way to write a function that adds an element to a list if the list does not contain it. Or otherwise removes it if the list does contain it, I'm using an if clause now and the function is working.
But I'm trying to find a more haskell-ish way to right this.
This is my code:
removeElemOrAdd :: Eq a => a -> [a] -> [a]
removeElemOrAdd elem list = if (List.elem elem list)
then (filter(\x -> x /= elem) list)
else (elem:list)
Note: a small ambiguity in your question is what to do when x already occurs multiple times in the original list. I assumed this won't happen and in case it does, only the first occurrence is removed. Meaning that removeElemOrAdd 2 [4,2,5,2,7] will result in [4,5,2,7]. Furthermore it is unspecified where the item should be added. Because it has some advantages, I've opted to do this at the end of the list.
An implementation without using any library methods is the following:
removeElemOrAdd :: Eq a => a -> [a] -> [a]
removeElemOrAdd x (y:ys) | x == y = ys
| otherwise = y : removeElemOrAdd x ys
removeElemOrAdd x _ = [x]
Or a shorter version:
removeElemOrAdd :: Eq a => a -> [a] -> [a]
removeElemOrAdd x = reoa
where reoa (y:ys) | x == y = ys
| otherwise = y : reoa ys
reoa _ = [x]
or an equivalent implementation (see discussion below):
removeElemOrAdd :: Eq a => a -> [a] -> [a]
removeElemOrAdd x = reoa
where reoa (y:ys) | x == y = ys
| otherwise = y : reoa ys
reoa [] = [x]
The function works as follows: in case we are talking about a list with at least one item (y:ys), we compare x with y and if they are equal, we return ys: in that case we have removed the element and we are done.
Now in case the two are not equal, we return a list construction (:) with y in the head since we need to retain y and in the tail, we will do a recursive call removeElemOrAdd with x and ys. Indeed: it is possible that there is an x somewhere in the tail ys to remove, and furthermore we still need to add x to the list if it does not occur.
That clause will loop recursively through the list. From the moment it finds an y such that x == y it will remove that y. It is however possible that we reach the end of the list, and still have not found the element. In that case we will call the final clause. Here we know the list is empty (we could have written removeElemOrAdd x []) but to make the function definition syntactically total, I have opted to use an underscore. We can only reach this state if we have failed to find x in the list, so then we add it to the tail of the list by returning [x].
An advantage of this approach over using the if-then-else is that this does all tasks at once (checking, removing and adding) making it more efficient.
Another advantage is that this can run on an "infinite" list (like for instance the list of prime numbers). The list is evaluated lazily, so if you want to take the first three items, this function will only check the equality of the first three items.
I like the other approaches, but don't like that they behave differently than the specification. So here is an approach that:
Like the original, deletes all copies, if there are any, AND
like the original, inserts the new value at the beginning, if necessary, BUT
unlike the original, uses a clever trick based on the ideas of beautiful folding (and follow-up developments) to make only one pass through the data.
The basic idea is that we will have a single value which tracks both whether all values so far have been a mismatch as well as the resulting filtered list. The injectNE operation will perform this operation for a single element of the list, and we will then use foldMap to expand from one element to the whole input list.
import Data.Monoid
injectNE :: Eq a => a -> a -> (All, [a])
injectNE old new = (All ne, [new | ne]) where
ne = old /= new
removeElemOrAdd :: Eq a => a -> [a] -> [a]
removeElemOrAdd x xs = case foldMap (injectNE x) xs of
(All nex, noxs) -> [x | nex] ++ noxs
In the final pattern, you should read nex as "no element was equal to x", and noxs as "the list without any copies of x" (get it? "no xs"? ba-dum-tsh).
It is slightly unfortunate that the spec was written the way it was, though: in particular, one of the selling points of beautiful folding is that its resulting one-pass folds can be friendlier to the garbage collector. But the spec makes that quite hard, because we must traverse the entire input list before deciding what the first element of the result list should be. We can improve the friendliness to the garbage collector significantly by relaxing point (2) above (but leaving (1) and (3)); and moreover the difference is merely swapping the arguments to (++), a nicely semantic diff to see in your revision history:
-- <snipped identical code>
removeElemOrAdd x xs = case ... of
... -> noxs ++ [x | nex]
I'd use a fold to remove all copies:
removeOrAdd x xs = foldr go (bool [x] []) xs False where
go y r found
| y == x = r True
| otherwise = y : r found
To remove just one, a paramorphism seems to be in order:
removeOrAdd x = para go [x] where
go y ys r
| y == x = ys
| otherwise = y : r
I have been working with Haskell for a little over a week now so I am practicing some functions that might be useful for something. I want to compare two lists recursively. When the first list appears in the second list, I simply want to return the index at where the list starts to match. The index would begin at 0. Here is an example of what I want to execute for clarification:
subList [1,2,3] [4,4,1,2,3,5,6]
the result should be 2
I have attempted to code it:
subList :: [a] -> [a] -> a
subList [] = []
subList (x:xs) = x + 1 (subList xs)
subList xs = [ y:zs | (y,ys) <- select xs, zs <- subList ys]
where select [] = []
select (x:xs) = x
I am receiving an "error on input" and I cannot figure out why my syntax is not working. Any suggestions?
Let's first look at the function signature. You want to take in two lists whose contents can be compared for equality and return an index like so
subList :: Eq a => [a] -> [a] -> Int
So now we go through pattern matching on the arguments. First off, when the second list is empty then there is nothing we can do, so we'll return -1 as an error condition
subList _ [] = -1
Then we look at the recursive step
subList as xxs#(x:xs)
| all (uncurry (==)) $ zip as xxs = 0
| otherwise = 1 + subList as xs
You should be familiar with the guard syntax I've used, although you may not be familiar with the # syntax. Essentially it means that xxs is just a sub-in for if we had used (x:xs).
You may not be familiar with all, uncurry, and possibly zip so let me elaborate on those more. zip has the function signature zip :: [a] -> [b] -> [(a,b)], so it takes two lists and pairs up their elements (and if one list is longer than the other, it just chops off the excess). uncurry is weird so lets just look at (uncurry (==)), its signature is (uncurry (==)) :: Eq a => (a, a) -> Bool, it essentially checks if both the first and second element in the pair are equal. Finally, all will walk over the list and see if the first and second of each pair is equal and return true if that is the case.