bla9x
bla9x

Reputation: 519

Haskell - List comprehension accessing next element as well

I'm trying to use list comprehension to return the list elements that differ from the next. So far I've got it working with patterns and guards but ultimately need to use list comprehension

So fn [4,3,3,1,1,3,3,3] and [4,3,1,3] would return [4,3,1]

This is what I've got so far which just returns an empty list

notEq'::[Int]->[Int]
notEq' il = [x | x <- il, fn il]
                where fn (a:b:xs) = a == b

Edit: Expanding more on the question, I want it to compare each element to the next and exclude the last comparison to []. So [4,3,3,1] would go something like this (4,3,OK), (3,3,NO), (3,1,OK) with the result [4,3]

Upvotes: 1

Views: 2574

Answers (2)

elm
elm

Reputation: 20435

Consider zipping each element of the list with its successor and filtering those pairs whose first and second item differ, like this,

notEq' :: [Int] -> [Int]
notEq' xs = map (fst) . filter (\(a,b) -> a /= b) $ zip xs (drop 1 xs)

For getting a list with labels, consider this,

pairing :: Eq t => (t, t) -> (t, t, [Char])
pairing (x,y) = (x,y,label)
  where
    label = if (x /= y) then "OK" else "NO"

and so

map (pairing) $ zip xs (drop 1 xs)

for [4,3,3,1,1,3,3,3] would deliver

[(4,3,"OK"),(3,3,"NO"),(3,1,"OK"),(1,1,"NO"),(1,3,"OK"),(3,3,"NO"),(3,3,"NO")]

Update

Using a comprehension, like this,

notEq' :: [Int] -> [Int]
notEq' xs = [ x | (x,y) <- zip xs (drop 1 xs), x /= y ]

Upvotes: 1

DaoWen
DaoWen

Reputation: 33029

The function you're describing and the example you gave seem to disagree.

The example output suggests that you're looking for a function that takes a list and returns a list of only the distinct elements. In that case, you're looking for nub:

nub [4,3,3,1,1,3,3,3]
-- result is [4,3,1]

However, the function you describe in English and in your code takes a list and removes adjacent duplicates. In that case, you would expect the result for both example inputs to be [4,3,1,3], not [4,3,1]. In that case, Haskell already has a function to group subsequences of adjacent, equal elements:

map head $ group [4,3,3,1,1,3,3,3]
-- result is [4,3,1,3]

If you must use a comprehension, maybe this will suffice:

[ x | x:xs <- group [4,3,3,1,1,3,3,3] ]
-- result is [4,3,1,3]

Now that you've clarified what you want to do, I think tails would be your friend here:

let xs = [4,3,3,1,1,3,3,3] in
  [ a | a:b:_ <- tails xs, a /= b ]
-- result is [4,3,1]

I really don't understand why you want to exclude the last element. If you by chance wanted to include it, it would be easy to accommodate:

let xs@(x:_) = [4,3,3,1,1,3,3,3] in
  x : [ b | a:b:_ <- tails xs, a /= b ]
-- result is [4,3,1,3]

Upvotes: 2

Related Questions