ElemIndices in Haskell
I wrote some code to get the index of an element
elemIndex :: [String] -> [String] -> [Int]
elemIndex [] [] = []
elemIndex x y = elemIndex True [(elem a y) | a <- x ]
is there an alternative way / simulator for doing the above logic?
and also i saw some use
index [] _ = []
to return null lists
Could you please explain the use of underscores?
// change 1 it should return the index of the values in the list.
for example: elemIndex ["asde", "zxc", "qwe"] ["qwe", "zxc"]
returns [1,2] as response
thanks
a source to share
elemIndex
takes two arguments (two lists). Right now, you are recursively calling this an extra argument of type bool (namely True
). It won't work. What you probably want to do is create a helper function, as I showed you an hour ago.
_
, used as a formal argument, matches any input. It has no name and therefore you cannot use what matches.
Also, you probably don't want to use booleans, but integers (to keep track of the counter). The function elem
only indicates whether a value is part of the list, not where it is. Thus, it is of little use to you. Since this appears to be homework, I won't offer a solution to your problem, but perhaps you should split the code in two:
indices :: (Eq t) => [t] -> [t] -> [Integer]
getIndex :: (Eq t) => [t] -> t -> Integer
( getIndex
can use a helper function getIndex' :: (Eq t) => [t] -> t -> Integer -> Integer
.)
Edit . One possible solution (which uses a hack, it is better to use a monad Maybe
):
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)
Monad version Maybe
:
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 the hard positions in the standard library:
import Data.List
import Data.Maybe
indices :: (Eq t) => [t] -> [t] -> [Int]
indices xs ys = mapMaybe (`elemIndex` xs) ys
a source to share
I would implement your function like this:
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 original list are in the same order as the elements you are looking for, this is much more efficient (no use elem
- tail recursion). Example:
elemIndex [3..7] [4, 6] -- Yields [2, 4]
a source to share