I am a beginner in Haskell so please bear with me. (Just started learning yesterday!) How can I sort a list of tuples primarily by their first components (highest to smallest) and secondarily by their second components (smallest to highest)? A sample input/output would be:
[(1, "b"), (1, "a"), (2, "b"), (2, "a")]
(input)
[(1, "a"), (2, "a"), (1, "b"), (2, "b")]
(middle step)
[(2, "a"), (2, "b"), (1, "a"), (1, "b")]
(output)
I tried using the following but it gave wrong output:
sortGT a b = GT sortBy sortGT lst
I am sure that I can do this by using sortBy
only, but I can't figure it out myself. Any help would be highly appreciated!
The sortBy function is the non-overloaded version of sort. >>> sortBy (\(a,_) (b,_) -> compare a b) [(2, "world"), (4, "!"), (1, "Hello")] [(1,"Hello"),(2,"world"),(4,"!")] sortBy sorts the specified Seq according to the specified comparator.
The sort function takes a list as the input and returns the sorted list as the output. The sort function sorts the elements of the given list in ascending order and returns it as a new list. The sort function is available in Data.
You need to construct your function sortGT
, so that it compares pairs the way you want it:
sortGT (a1, b1) (a2, b2) | a1 < a2 = GT | a1 > a2 = LT | a1 == a2 = compare b1 b2
Using this you get the following results (I used ghci):
*Main Data.List> sortBy sortGT [(1, "b"), (1, "a"), (2, "b"), (2, "a")] [(2,"a"),(2,"b"),(1,"a"),(1,"b")]
May I suggest the following?
import Data.List (sortBy) import Data.Monoid (mconcat) myPredicate (a1, a2) (b1, b2) = mconcat [compare b1 a1, compare a2 b2]
You can then sort by writing sortBy myPredicate lst
. The function mconcat
simply scans through the list and obtains the first non-EQ
occurence (or EQ
if all elements are EQ
and thus both pairs are considered equal).
On second thought, building the list isn't necessary.
import Data.List (sortBy) import Data.Monoid (mappend) myPredicate (a1, a2) (b1, b2) = compare b1 a1 `mappend` compare a2 b2
The definition of mappend
for Ordering
is essentially:
EQ `mappend` x = x x `mappend` _ = x
Which is exactly what we need.
Just for fun, generalizing gbacon's answer and making the use a little more flexible:
import Data.Ord import Data.List import Data.Monoid ascending = id descending = flip sortPairs f x g y = f (comparing x) `mappend` g (comparing y) mySort = sortBy (sortPairs descending fst ascending snd)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With