Bohtvaroh

Lists intersection, subtraction, difference

Oct 2nd, 2012
109
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import Data.List (sort)
  2.  
  3. -- |Finds lists intersection. O(2nlogn + 2n)
  4. intersection :: Ord a => [a] -> [a] -> [a]
  5. intersection = iter intersectF
  6.  
  7. intersectF :: Eq a => (Maybe a, Maybe a) -> [a] -> [a]
  8. intersectF (Just x, Just y) acc = if x == y then x:acc else acc
  9. intersectF _ acc = acc
  10.  
  11. -- |Subtracts second list from the first. O(2nlogn + 2n)
  12. subtraction :: Ord a => [a] -> [a] -> [a]
  13. subtraction = iter subtractF
  14.  
  15. subtractF :: Eq a => (Maybe a, Maybe a) -> [a] -> [a]
  16. subtractF (Just x, Just y) acc = if x /= y then x:acc else acc
  17. subtractF (Just x, Nothing) acc = x:acc
  18. subtractF _ acc = acc
  19.  
  20. -- |Finds symmetric difference between lists. O(2nlogn + 2n)
  21. difference :: Ord a => [a] -> [a] -> [a]
  22. difference = iter diffF
  23.  
  24. diffF :: Eq a => (Maybe a, Maybe a) -> [a] -> [a]
  25. diffF (Just x, Just y) acc = if x /= y then x:y:acc else acc
  26. diffF (Just x, Nothing) acc = x:acc
  27. diffF (Nothing, Just y) acc = y:acc
  28. diffF _ acc = acc
  29.  
  30. -- |Iterates two sorted lists at once.
  31. -- Concrete behavior is incapsulated in the supplied function. O(n)
  32. iter :: Ord a => ((Maybe a, Maybe a) -> [a] -> [a]) -> [a] -> [a] -> [a]
  33. iter f xs ys = foldr f [] (join (sort xs) (sort ys))
  34.  
  35. -- |Joins two sorted lists into list of pairs similarly to SQL full join. O(n)
  36. join :: Ord a => [a] -> [a] -> [(Maybe a, Maybe a)]
  37. join xs ys = join' xs ys []
  38.  where join' [] [] acc = acc
  39.         join' (x:xs) [] acc = join' xs [] ((Just x, Nothing):acc)
  40.         join' [] (y:ys) acc = join' [] ys ((Nothing, Just y):acc)
  41.         join' allXs@(x:xs) allYs@(y:ys) acc =
  42.          let (x', y', xs', ys') = case x `compare` y of
  43.                EQ -> (Just x, Just y, xs, ys)
  44.                GT -> (Nothing, Just y, allXs, ys)
  45.                LT -> (Just x, Nothing, xs, allYs)
  46.          in join' xs' ys' $ (x', y'):acc
Advertisement
Add Comment
Please, Sign In to add comment