I am trying to print every second element from list of lists
fun [[1,2,3],[4,5,6],[6,7,8]] = [2,5,7]
I have this:
fun xs = fmap head xs
but this returns every first elem from lists
I Just changed the output to [Maybe a] because using just fmap or map with head.tail cant handle the exception of shorter lists.
Also I generalized to N'th index:
takeNthIndex :: (Eq t, Num t) => t -> [a] -> Maybe a
takeNthIndex _ [] = Nothing
takeNthIndex 0 (x:xs) = Just x
takeNthIndex n (x:xs) = takeNthIndex (n-1) xs
everyNthIndex :: (Eq t, Num t) => t -> [[a]] -> [Maybe a]
everyNthIndex _ [] = []
everyNthIndex n (x:xs) = takeNthIndex n x : everyNthIndex n xs
everyNthIndexByMap :: (Eq t, Num t) => t -> [[a]] -> [Maybe a]
everyNthIndexByMap n = map (takeNthIndex n)
Usage:
everyNthIndex 1 [[1,2,3],[4,5,6],[6,7,8], []]
-- output: [Just 2,Just 5,Just 7,Nothing]
everyNthIndex is the recursive version of everyNthIndexByMap
Related
I am trying to check whether my second part of my tuple is 1.0 and if it is then I am storing it in the list. But I can't figure out how to implement the check.
number :: [(Integer, Double)] -> [Integer]
number lst = number' lst []
where
number' [] a = a
((mat,1.0): xs) a = number'(xs) (mat:a) -- Here I am getting my error
((_,lst): xs) a = number'(xs) a
Maybe someone has an idea.
The reason this doesn't work is because you need to write number' for every line:
number :: [(Integer, Double)] -> [Integer]
number lst = number' lst []
where
number' [] a = a
number' ((mat,1.0): xs) a = number'(xs) (mat:a)
number' ((_,lst): xs) a = number'(xs) a
But this will return the "keys" in reverse.
You can pattern match with:
number :: (Eq a, Num a) => [(a, b)] -> [a]
number ((x, 1):xs) = x : number xs
number (_:xs) = number xs
number [] = []
You can however work with list comprehension:
number :: (Eq a, Num a) => [(a, b)] -> [a]
number xs = [ x | (x, 1) <- xs ]
or with a combination of map and filter:
number :: (Eq a, Num a) => [(a, b)] -> [a]
number = map fst . filter ((1 ==) . snd)
I am trying to split a list whenever f returns true, for example:
separate even [1,2,3,4] = [[2],[4]]
Current code:
separate f (x:xs) currentstr finalstr
| f x = (finalstr ++ currentstr) : separate f xs [] finalstr
| otherwise = (currentstr ++ x) : separate f xs (currentstr + x) finalstr
separate f [] currentstr finalstr = []
Can anyone provide some insight on how to fix this? Values for currentstr and finalstr will be provided as [] in another function always, so this is not a concern.
You could divide your problem into the following sub-problems:
Split a list in two where the first sequence is equivalent when applying f to each element:
splitOn :: Eq b => (a -> b) -> [a] -> ([a], [a])
splitOn f [] = ...
splitOn f (x:xs) = ...
For example,
> splitOn odd [1,3,3,4,5]
([1,3,3], [4,5])
Group each element in the list by what f returns:
groupOn :: Eq b => (a -> b) -> [a] -> [[a]]
groupOn f [] = ...
groupOn f xs = ...
For example,
> groupOn odd [1,3,3,4,5,6,8]
[[1,3,3],[4],[5],[6,8]]
You can do this by applying splitOn recursively. Think case-of.
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.
I have created a program to remove first smallest element but I dont how to do for second largest:
withoutBiggest (x:xs) =
withoutBiggestImpl (biggest x xs) [] (x:xs)
where
biggest :: (Ord a) => a -> [a] -> a
biggest big [] = big
biggest big (x:xs) =
if x < big then
biggest x xs
else
biggest big xs
withoutBiggestImpl :: (Eq a) => a -> [a] -> [a] -> [a]
withoutBiggestImpl big before (x:xs) =
if big == x then
before ++ xs
else
withoutBiggestImpl big (before ++ [x]) xs
Here is a simple solution.
Prelude> let list = [10,20,100,50,40,80]
Prelude> let secondLargest = maximum $ filter (/= (maximum list)) list
Prelude> let result = filter (/= secondLargest) list
Prelude> result
[10,20,100,50,40]
Prelude>
A possibility, surely not the best one.
import Data.Permute (rank)
x = [4,2,3]
ranks = rank (length x) x -- this gives [2,0,1]; that means 3 (index 1) is the second smallest
Then:
[x !! i | i <- [0 .. length x -1], i /= 1]
Hmm.. not very cool, let me some time to think to something better please and I'll edit my post.
EDIT
Moreover my previous solution was wrong. This one should be correct, but again not the best one:
import Data.Permute (rank, elems, inverse)
ranks = elems $ rank (length x) x
iranks = elems $ inverse $ rank (length x) x
>>> [x !! (iranks !! i) | i <- filter (/=1) ranks]
[4,2]
An advantage is that this preserves the order of the list, I think.
Here is a solution that removes the n smallest elements from your list:
import Data.List
deleteN :: Int -> [a] -> [a]
deleteN _ [] = []
deleteN i (a:as)
| i == 0 = as
| otherwise = a : deleteN (i-1) as
ntails :: Int -> [a] -> [(a, Int)] -> [a]
ntails 0 l _ = l
ntails n l s = ntails (n-1) (deleteN (snd $ head s) l) (tail s)
removeNSmallest :: Ord a => Int -> [a] -> [a]
removeNSmallest n l = ntails n l $ sort $ zip l [0..]
EDIT:
If you just want to remove the 2nd smallest element:
deleteN :: Int -> [a] -> [a]
deleteN _ [] = []
deleteN i (a:as)
| i == 0 = as
| otherwise = a : deleteN (i-1) as
remove2 :: [a] -> [(a, Int)] -> [a]
remove2 [] _ = []
remove2 [a] _ = []
remove2 l s = deleteN (snd $ head $ tail s) l
remove2Smallest :: Ord a => [a] -> [a]
remove2Smallest l = remove2 l $ sort $ zip l [0..]
It was not clear if the OP is looking for the biggest (as the name withoutBiggest implies) or what. In this case, one solution is to combine the filter :: (a->Bool) -> [a] -> [a] and maximum :: Ord a => [a] -> a functions from the Prelude.
withoutBiggest l = filter (/= maximum l) l
You can remove the biggest elements by first finding it and then filtering it:
withoutBiggest :: Ord a => [a] -> [a]
withoutBiggest [] = []
withoutBiggest xs = filter (/= maximum xs) xs
You can then remove the second-biggest element in much the same way:
withoutSecondBiggest :: Ord a => [a] -> [a]
withoutSecondBiggest xs =
case withoutBiggest xs of
[] -> xs
rest -> filter (/= maximum rest) xs
Assumptions made:
You want each occurrence of the second-biggest element removed.
When there is zero/one element in the list, there isn't a second element, so there isn't a second-biggest element. Having the list without an element that isn't there is equivalent to having the list.
When the list contains only values equivalent to maximum xs, there also isn't a second-biggest element even though there may be two or more elements in total.
The Ord type-class instance implies a total ordering. Otherwise you may have multiple maxima that are not equivalent; otherwise which one is picked as the biggest and second-biggest is not well-defined.
I wrote the code to get the element index
elemIndex :: [String] -> [String] -> [Int]
elemIndex [] [] = []
elemIndex x y = elemIndex True [(elem a y) | a <- x ]
is there any alternative way/similer of performing the above logic?
and also i've seen that some use
index [] _ = []
to return null lists
could you pls explain the use of underscore?
//edit 1
it is suposed to return the index of the values in the list.
eg: elemIndex ["asde","zxc","qwe"] ["qwe","zxc"]
returns [1,2] as the answer
thanks
elemIndex takes two arguments (two lists). Right now you recursively call it with an additional argument of type bool (namely True). That will not work. What you probably want to do, is create a helper function, as I showed you an hour ago.
The _, as used as a formal argument, matches any input. It does not have a name, and as such, you cannot use that which is matched.
Aside from that, you probably don't want to use booleans, but integers (to keep track of a counter). The elem function only tells you whether some value is part of a list, not where it is. So, it is of little use to you. Since this appears to be homework I will not provide a solution to your problem, but perhaps you should split your code in two:
indices :: (Eq t) => [t] -> [t] -> [Integer]
getIndex :: (Eq t) => [t] -> t -> Integer
(getIndex may use a helper function getIndex' :: (Eq t) => [t] -> t -> Integer -> Integer.)
Edit: One possible solution (which uses a hack, it's nicer to use the Maybe monad):
indices :: (Eq t) => [t] -> [t] -> [Integer]
indices xs ys = filter (>= 0) $ map (getIndex xs) ys
getIndex :: (Eq t) => [t] -> t -> Integer
getIndex xs y = getIndex' xs y 0
where
getIndex' :: (Eq t) => [t] -> t -> Integer -> Integer
getIndex' [] _ _ = -1
getIndex' (x:xs) y i | x == y = i
| otherwise = getIndex' xs y (i + 1)
A version with the Maybe monad:
import Data.Maybe
indices :: (Eq t) => [t] -> [t] -> [Integer]
indices xs ys = mapMaybe (getIndex xs) ys
getIndex :: (Eq t) => [t] -> t -> Maybe Integer
getIndex xs y = getIndex' xs y 0
where
getIndex' :: (Eq t) => [t] -> t -> Integer -> Maybe Integer
getIndex' [] _ _ = Nothing
getIndex' (x:xs) y i | x == y = Just i
| otherwise = getIndex' xs y (i + 1)
And a version that leaves all heavy lifting to the standard library:
import Data.List
import Data.Maybe
indices :: (Eq t) => [t] -> [t] -> [Int]
indices xs ys = mapMaybe (`elemIndex` xs) ys
index [] _ = []
is the same as
index [] x = []
except you cannot use the _ on the right hand side of the equals sign.
I don't understand what you want elemIndex to do.
I'd implement your function this way:
elemIndices acc n [] _ = acc
elemIndices acc n _ [] = acc
elemIndices acc n (x:x') (y:y') = if x == y then
elemIndices (n:acc) (n+1) x' y'
else
elemIndices acc (n+1) x' (y:y')
elemIndex x y = reverse $ elemIndices [] 1 x y
When the elements in your source list are in the same order as the elements you look for, this is much more efficient (no use of elem - tail recursion). Ex:
elemIndex [3..7] [4, 6] -- Yields [2, 4]
Im doing a project in Haskell where I am trying to create a function which takes two list inputs and then returns a union of the list but without any duplicates.
The problem is that I keep getting the error message:
Couldn't match expected type ‘a’ with actual type ‘[t0]’
‘a’ is a rigid type variable bound by
the type signature for newList :: [a] -> [a] -> [a]
Here is my code:
allList :: (Eq a) => [a] -> [a] -> [a]
allList [] [] = []
allList x y = (x ++ y)
checkDup [] = []
checkDup (z:zs)
| z `elem` zs = checkDup zs
| otherwise = z : checkDup zs
newList :: (Eq a) => [a] -> [a] -> [a]
newList [] [] = []
newList x y = [checkDup z | z <- allList x y]
The first allList function creates a list of the two list, the checkDup creates a new list without any duplicates and the newList uses list comprehension to pass the combined list to the checkDup.
Anyone know where I am going wrong?
The problem lies here:
newList x y = [checkDup z | z <- allList x y]
z is supposed to be a list you pass to checkDup, but in this case, z is just a single element
Maybe you want:
newList x y = checkDup $ allList x y
newList can be declared as follows:
newList :: (Eq a) => [a] -> [a] -> [a]
newList = checkDup . allList
Since #Smac89 answered your question, why not use a data representation like Data.Set?
import qualified Data.Set as S
allList :: Ord a => [a] -> [a] -> [a]
allList xs ys = S.toList $ S.union (S.fromList xs) (S.fromList ys)
(although the continued use of Sets is probably even more meaningful.)
Or by using Data.List:
import Data.List
newList :: Eq a => [a] -> [a] -> [a]
newList xs ys = nub $ xs ++ ys