11

How can it be done in most simply way to write (or maybe there is something embedded in haskell) function which takse as arguments list of tuples (String, Int) and Int x and return top x tuples as list according to x value.

I wonder if its possible to write a function which also takes 3 argument which is the name of (or index) of filed in tuple according to which sorting has to be done.

What are best solutions to make it quite generic?

Chris Martin
  • 30,334
  • 10
  • 78
  • 137
gruber
  • 28,739
  • 35
  • 124
  • 216
  • I know your question is probably more for your own curiosity, but what are you doing with the data? Is a sorted list really what you want to end up with? We're not shuffling around elements in low-level arrays in C country anymore and haskell gives you easy access to a whole zoo of interesting data types which probably are more appropriate for doing whatever you're going to be doing with the "sorted" data. – jberryman May 07 '10 at 18:49
  • The reason is that Im learning and want to know what are possibilities, and sort function is the one that everyone understand so the explenation is easier. Ofcourse I know about embedded types, still learning, thanks – gruber May 08 '10 at 22:05

1 Answers1

28
take x $ sortBy (compare `on` fst) [("asd", 1), ...]

take x takes the first x items from the sorted list. sortBy sorts the list given as second argument using the sorting function given as the first argument. (compare `on` fst) compares the first values of each tuple. Note that this example compares the first value of each tuple for sorting. To sort by the second value, replace fst with snd.

You see that the sortBy function is very generic, as it lets you define the function used to compare the values. The function takes two arguments and should return one of LT, EQ or GT. Note that the function compare requires both arguments to derive from Ord. The helper function on can be found in the module Data.Function. The function sortBy is in the module Data.List.

EDIT: Here is a complete working example that sorts a list of tuples by comparing their first values and prints the first 2 tuples of the resulting list. Note that I replaced the on from the example above with a equivalent function that shows what on does internally.

import Data.Function
import Data.List

main = print $ mySort [("foo", 1), ("bar", 2), ("baz", 3), ("quux", 4)] 2

mySort list x = take x $ sortBy (\ x y -> compare (fst x) (fst y)) list

EDIT: As Tom Lokhorst pointed out in his comment, the function comparing from the module Data.Ord is a more readable replacement/shortcut for on compare, so the above could also be written as sortBy (comparing fst).

jkramer
  • 15,440
  • 5
  • 47
  • 48
  • 8
    Note that the `comparing` function from `Data.Ord` is the same as `on compare`. So you could also write `sortBy (comparing fst) list`. – Tom Lokhorst May 07 '10 at 13:14
  • Nice, I didn't know that one. – jkramer May 07 '10 at 14:02
  • Should you not `take` before you `sortBy`? mySort can potentially take an infinite list. – Andre Artus Apr 10 '14 at 17:49
  • 1
    Since `base-4.8.0.0`, `Data.List` provides `sortOn` (in this case: `sortOn fst`). @AndreArtus if you take first, you are just getting the first x, not the top x according to sorting. Sorting an infinite list doesn't really make sense anyway! – Daniel Buckmaster Sep 27 '15 at 05:48