Reputation: 378
I’m doing my homework in Haskell and I got to a point where I need to compare two lists element by element and count how many elements are the same and in the same place: the first element of the first list with the first element of the second list, etc..
Here’s what I have:
compare :: [Int]->[Int]->Int
compare [a] [b]= if head a == head b then 1 + compare (tail a tail b) else 0 + compare (tail a tail b)
compare [] [b] = 0
I know in advance that they will both be lists with 8 Int
s as elements.
Upvotes: 1
Views: 6122
Reputation: 224862
The problems with your code are:
The patterns: you’re defining compare [a] [b]
, but you want a
and b
to be lists because you’re using them with head
and tail
. Just define compare a b
instead.
The order of the patterns: the first match wins, so your compare [] b = 0
should come first.
compare (tail a tail b)
should be giving two arguments to compare
, not three arguments to tail
. compare (tail a) (tail b)
.
All told:
compare :: [Int] -> [Int] -> Int
compare [] _ = 0
compare a b =
if head a == head b then
1 + compare (tail a) (tail b)
else
compare (tail a) (tail b)
And although it probably isn’t suitable for homework, it might be fun to know that you can write this by getting a list of booleans indicating whether certain positions are equal, filtering them to only true values, and getting the resulting length:
compare a = length . filter id . zipWith (==) a
-- this works too
compare a = sum . fromEnum . zipWith (==) a
Upvotes: 3
Reputation: 1228
You could zip
the two lists and then compare on the resulting tuples lists
map (uncurry compare) $ zip l1 l2
assuming you have two lists l1
and l2
and to count all places where they have the same elements
length $ filter (== EQ) $ map (uncurry compare) $ zip l1 l2
Upvotes: 2