tags:

views:

212

answers:

3

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

+1  A: 
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.

Dave Hinton
+1  A: 

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
Stephan202
thanks, the code i've used gives me the desired output. but i jus want to find out a different of tackling the issue.
pier
Good to hear you have a solution. I updated my answer to include the solution I hinted at.
Stephan202
im confused a bitys=["as","sas"]zip [1..] ys woudl give[(1,"as"),(2,"sas")] as ive mentioned earlier, elemIndex ["asde","zxc","qwe"] ["qwe","zxc"] would yield [2,1] since index of "qwe" is 2 and "zxc" is 1so in this case zip function is helpful? or have i incorrectly used it?thanks
pier
Ah, in your question you stated that it should be [1,2] instead of [2,1]. When i read that, I assumed you wanted the indices in the second list, 1-indexed. So my initial hunch *was* correct. I'll add another solution in a minute.
Stephan202
...done (and removed the code based on my incorrect assumption; you can still find it in the edit history).
Stephan202
great help! thanks :)
pier
A: 

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]
Dario
Ah - I got you wrong. You want to have the indices in the first list. Sorry
Dario