Top rank per group

From Rosetta Code
Task
Top rank per group
You are encouraged to solve this task according to the task description, using any language you may know.

Find the top N rankers per group.

Haskell

import Data.List
import Control.Monad
import Control.Arrow
import Text.Printf

groupingOn f a b = f a == f b
comparing f a b = compare (f a) (f b)
comparingDwn f a b = compare (f b) (f a)


type ID = Int
type DEP = [Char]
type NAME = [Char]
type SALARY = Double
type Employee = (ID, DEP, NAME, SALARY)

employees :: [Employee]
employees = [(1001,"AB","Janssen A.H.",41000), (101,"KA","'t Woud B.",45000),
             (1013,"AB","de Bont C.A.",65000), (1101,"CC","Modaal A.M.J.",30000),
             (1203,"AB","Anders H.",50000),    (100,"KA","Ezelbips P.J.",52000),
             (1102,"CC","Zagt A.",33000),     (1103,"CC","Ternood T.R.",21000),
             (1104,"CC","Lageln M.",23000),   (1105,"CC","Amperwat A.",19000),
             (1106,"CC","Boon T.J.",25000), (1107,"CC","Beloop L.O.",31000),
             (1009,"CD","Janszoon A.",38665), (1026,"CD","Janszen H.P.",41000),
             (1011,"CC","de Goeij J.",39000), (106,"KA","Pragtweik J.M.V.",42300),
             (111,"KA","Bakeuro S.",31000),  (105,"KA","Clubdrager C.",39800),
             (104,"KA","Karendijk F.",23000), (107,"KA","Centjes R.M.",34000),
             (119,"KA","Tegenstroom H.L.",39000), (1111,"CD","Telmans R.M.",55500),
             (1093,"AB","de Slegte S.",46987), (1199,"CC","Uitlaat G.A.S.",44500)
            ]

nr :: Employee -> ID
nr   (i,_,_,_) = i

dep :: Employee -> DEP
dep  (_,d,_,_) = d

name :: Employee -> NAME
name (_,_,n,_) = n

sal :: Employee -> SALARY
sal  (_,_,_,s) = s

dorank :: Int ->
          (Employee -> DEP) ->
          (Employee -> SALARY) ->
          [Employee]-> [[Employee]]
dorank n o1 o2 = map (take n. sortBy (comparingDwn o2))
                 . groupBy (groupingOn o1) . sortBy (comparing o1)

toprank :: IO ()
toprank = do
   printf "%-16s %3s %10s\n" "NAME" "DEP" "TIP" 
   printf "%s\n" $ replicate 31 '='
   mapM_ (mapM_ (ap (ap (printf "%-16s %3s %10.2g\n" . name) dep) sal)) $ dorank 3 dep sal employees

Output: top 3 per department

*Main> toprank
NAME             DEP        TIP
===============================
de Bont C.A.      AB   65000.00
Anders H.         AB   50000.00
de Slegte S.      AB   46987.00
Uitlaat G.A.S.    CC   44500.00
de Goeij J.       CC   39000.00
Zagt A.           CC   33000.00
Telmans R.M.      CD   55500.00
Janszen H.P.      CD   41000.00
Janszoon A.       CD   38665.00
Ezelbips P.J.     KA   52000.00
't Woud B.        KA   45000.00
Pragtweik J.M.V.  KA   42300.00

SMEQL

The following SMEQL example returns the top 6 earners in each department based on this table schema:

 table: Employees
 ----------------
 empID
 dept
 empName
 salary 

Source Code:

 srt = orderBy(Employees, (dept, salary), order)
 top = group(srt, [(dept) dept2, max(order) order])
 join(srt, top, a.dept=b.dept2 and b.order - a.order < 6)