How can I delete an item from a list in Haskell?
I've got this code but it doesn't seems to work. The concept its, I've got 2 lists, the aList will always have just one element. bList will always have the element that its in aList. So I want to delete the element from bList and at the end, output the new list without that item. Could give some hints please?
Thanks
removeFromList :: aList -> bList -> finalList
removeFromList [] _ = []
removeFromList (y:ys) (x:xs)
| y == x = removeFromDatabase y xs
| otherwise = y : removeFromDatabase y xs
removeFromList :: Eq a => [a] -> [a] -> [a]
removeFromList _ [] = []
removeFromList (y:ys) (x:xs)
| y == x = removeFromList [y] xs
| otherwise = x : removeFromList [y] xs
There are a few issues:
The first list should contain the element but you appear to be getting it from the second in the first clause, so it should be:
removeFromList _ [] = []
Secondly, you need to recreate the list containing the single element when making the recursive calls i.e. removeFromList [y] xs
Thirdly the list types should be the same, and you need the Eq constraint for ==
As long as you always have a single element in aList, I'd propose another solution:
removeFromList :: Eq a => [a] -> [a] -> [a]
removeFromList [elem] = filter (== elem)
Or, if you have only one occurence of that element:
import Data.List
removeFromList [elem] = delete elem
But remember, it will fail if the first argument somehow appears to be empty or have more than one element.
Problems in your code:
You use aList and bList not as argument names, but as type variables in the function signature, which are too general (equivalent to removeFromList :: a -> b -> c)
When you recursively call the function, you pass y which is a single element, not a list.
Related
I want to extract the first element and all of its occurrences from a list and put them in the end of a list in Haskell
What I have now is this.
relegate [] = []
relegate (x:xs) = xs ++ [x]
With input [3 ,1 ,4 ,3 ,5 ,3 ,8] it returns me [1,4,3,5,3,8,3] but I wanted instead to return this list [1 ,4 ,5 ,8 ,3 ,3 ,3].
Right now you're just adding x to the end, which will only move the first occurrence, not all of them. You should instead find all equal elements, and remove them from the list. This can be done with partition in Data.List, which takes a predicate function and gets a list of elements that matches the predicate and a list that doesn't:
import Data.List
relegate :: (Eq a) => [a] -> [a]
relegate [] = []
relegate l#(x:_) = nonMatching ++ matching
where (nonMatching, matching) = partition (/= x) l
Or, more pointfree:
import Data.List
relegate :: (Eq a) => [a] -> [a]
relegate [] = []
relegate l = uncurry (++) $ partition (/= head l) l
This algorithm requires to first determine that first element x, and then enumerate over the list, here we will yield all elements that are different from x, and keep track of the number of times we have found an element that is equal to x, and when we reach the end of the list, we replicate x the number of times we encountered x in the list:
relegate :: Eq a => [a] -> [a]
relegate [] = []
relegate (x:xs) = go xs 1
where go [] n = replicate n x
go (y:ys) m
| x == y = go ys (m+1)
| otherwise = y : go ys m
This of course assumes that if x == y, then x and y are the same element. If that is not the case, you should work with an accumulator that keeps track of the equal elements.
Im new to haskell and Im writing a function that compares two sequences and reports the length of the prefix they have in common. This is what I have so far but it doesn't work for all cases.
commonLen :: Eq a => [a] -> [a] -> Int
commonLen (x:xs) [] = 0
commonLen (x:xs) (y:ys) | x==y = 1+(commonLen xs ys)
| otherwise = commonLen xs ys
Any ideas where im going wrong? Any help would be appreciated
You should not recurse in case x is different from y. In that case we return 0:
commonLen :: Eq a => [a] -> [a] -> Int
commonLen [] _ = 0
commonLen _ [] = 0
commonLen (x:xs) (y:ys) | x == y = 1 + commonLen xs ys
| otherwise = 0 -- ← return 0
You also can avoid the explicit recursion, and work with:
commonLen :: Eq a => [a] -> [a] -> Int
commonLen xs ys = length (takeWhile id (zipWith (==) xs ys))
here we iterate over both lists concurrently, and compare the elements. We thus make a list of Bools that is True if the elements of the two lists match. Then we use takeWhile to take elements as long as the item is True, and we use length to determine the number of elements in that list. Due to Haskell's laziness, we will never evaluate the entire list if one of the elements differs from the corresponding element in the other list.
I am trying to produce an output where the input list is split each time f x is true. I use two variables to keep track of the substring and the final list, and this function will be called by another that provides empty lists for two tracking variables. Example desired output:
separate odd [1,2,3,4] = [[2],[4]]
Below is what I have so far - although I keep running into type errors because lists all have to be of the same type - can anyone advise what changes need to be made to produce the desired output?
separate f (x:xs) sublist finalstr
| f x = (finalstr ++ sublist) : separate f xs sublist finalstr
| otherwise = (sublist ++ x) : separate f xs sublist finalstr
separate f [] sublist finalstr = []
You could divide your problem into the following sub-problems:
Group each element in the list by what f returns:
groupOn :: Eq b => (a -> b) -> [a] -> [[a]]
groupOn f = ...
For example,
> groupOn odd [1,3,3,4,5,6,8]
[[1,3,3],[4],[5],[6,8]]
Filter out sub-lists in which the first element satisfies f:
separate :: (a -> Bool) -> [a] -> [[a]]
separate f xs = filter (\ys -> ...) (groupOn f xs)
where ys would be [1,3,3], [4], [5] and [6,8] in the above example.
My ultimate goal is to find if a list y contains all the elements of list x (I'm checking if x is a subset of y sort of thing)
subset x y =
and [out | z <- x
, out <- filter (==z) y ]
This doesn't work, and I know it's because z is a list still. I'm trying to make sense of this.
I think I may have to use the elem function, but I'm not sure how to split x into chars that I can compare separately through y.
I'm ashamed to say that I've been working on this simple problem for an hour and a half.
Checking whether all elements of xs are elements of ys is very straightforward. Loop through xs, and for each element, check if it is in ys:
subset xs ys = all (\x -> elem x ys) xs
You could also use the list difference function (\\). If you have list y and list x, and you want to check that all elements of x are in y, then x \\ y will return a new list with the elements of x that are not in y. If all the elements of x are in y, the returned list will be empty.
For example, if your list y is [1,2,3,4,5] and your list x is [2,4], you can do:
Prelude> [2,4] \\ [1,2,3,4,5]
[]
If list y is [1,2,3,4,5] and list x is [2,4,6], then:
Prelude> [2,4,6] \\ [1,2,3,4,5]
[6]
Easy way to reason about subsets is to use sets as the data type.
import qualified Data.Set as S
subset :: Ord a => [a] -> [a] -> Bool
subset xs ys = S.isSubsetOf (S.fromList xs) (S.fromList ys)
Then it's as simple as:
*Main> subset [1..5] [1..10]
True
*Main> subset [0..5] [1..10]
False
Let's break this down into two subproblems:
Find if a value is a member of a list;
Use the solution to #1 to test whether every value in a list is in the second one.
For the first subproblem there is a library function already:
elem :: (Eq a, Foldable t) => a -> t a -> Bool
Lists are a Foldable type, so you can use this function with lists for t and it would have the following type:
elem :: (Eq a) => a -> [a] -> Bool
EXERCISE: Write your own version of elem, specialized to work with lists (don't worry about the Foldable stuff now).
So now, to tackle #2, one first step would be this:
-- For each element of `xs`, test whether it's an element of `ys`.
-- Return a list of the results.
notYetSubset :: Eq a => [a] -> [a] -> [Bool]
notYetSubset xs ys = map (\x -> elem x ys) xs
After that, we need to go from the list of individual boolean results to just one boolean. There's a standard library function that does that as well:
-- Return true if and only if every element of the argument collection is
-- is true.
and :: Foldable t => t Bool -> Bool
EXERCISE: write your own version of and, specialized to lists:
myAnd :: [Bool] -> Bool
myAnd [] = _fillMeIn
myAnd (x:xs) = _fillMeIn
With these tools, now we can write subset:
subset :: Eq a => [a] -> [a] -> [Bool]
subset xs ys = and (map (\x -> elem x ys) xs)
Although a more experienced Haskeller would probably write it like this:
subset :: Eq a => [a] -> [a] -> [Bool]
subset xs ys = every (`elem` ys) xs
{- This:
(`elem` ys)
...is a syntactic shortcut for this:
\x -> x elem ys
-}
...where every is another standard library function that is just a shortcut for the combination of map and and:
-- Apply a boolean test to every element of the list, and
-- return `True` if and only if the test succeeds for all elements.
every :: (a -> Bool) -> [a] -> Bool
every p = and . map p
I'm fairly new to Haskell and trying to figure out how I would write a Function to do this and after combing Google for a few hours I'm at a loss on how to do it.
Given the following two lists in Haskell
[(500,False),(400,False),(952,True),(5,False),(42,False)]
[0,2,3]
How would I change the Boolean of the First list at each location given by the second list to a Value of True for an Output of
[(500,True),(400,False),(952,True),(5,True),(42,False)]
This is how I would do it (assumes the list of indexes to replace is sorted).
First we add an index list alongside the list of indexes to replace and the original list.
Then we recurse down the list and when we hit the next index to replace we replace the boolean and recurse on the tail of both all three lists. If this is not an index to
replace we recurse on the entire replacement index list and the tail of the other two lists.
setTrue :: [Int] -> [(a, Bool)] -> [(a, Bool)]
setTrue is xs = go is xs [0..] -- "Index" the list with a list starting at 0.
where
go [] xs _ = xs -- If we're out of indexes to replace return remaining list.
go _ [] _ = [] -- If we run out of list return the empty list.
go indexes#(i:is) (x:xs) (cur:cs)
| i == cur = (fst x, True) : go is xs cs -- At the next index to replace.
| otherwise = x : go indexes xs cs -- Otherwise, keep the current element.
This is basically the same as Andrew's approach, but it doesn't use an additional index list, and is a little bit more inspired by the traditional map. Note that unlike map, the provided function must be a -> a and cannot be a -> b.
restrictedMap :: (a -> a) -> [Int] -> [a] -> [a]
restrictedMap f is xs = go f is xs 0
where
go f [] xs _ = xs
go f _ [] _ = []
go f ind#(i:is) (x:xs) n
| i == n = f x : go f is xs (n+1)
| otherwise = x : go f ind xs (n+1)
setTrue = restrictedMap (\(x,_) -> (x, True))
Straightforward translation from the description will be:
setIndexTrue f a = [(x, p || i `elem` f) | (i, (x,p)) <- zip [0..] a]
Or using the fantastic lens library:
setTrue :: [(a,Bool)] -> Int -> [(a,Bool)]
setTrue xs i = xs & ix i . _2 .~ True
setTrues :: [(a,Bool)] -> [Int] -> [(a,Bool)]
setTrues = foldl setTrue
Since the approach I would use is not listed:
setTrue spots values = let
pattern n = replicate n False ++ [True] ++ Repeat False
toSet = foldl1 (zipWith (||)) $ map pattern spots
in zipWith (\s (v,o) -> (v, o || s)) toSet values