Top rank per group: Difference between revisions

m
m (→‎{{header|Wren}}: Minor tidy)
 
(28 intermediate revisions by 19 users not shown)
Line 22:
</pre>
<br>
 
=={{header|11l}}==
{{trans|Python}}
 
<syntaxhighlight lang="11l">V data = [(‘Tyler Bennett’, ‘E10297’, 32000, ‘D101’),
(‘John Rappl’, ‘E21437’, 47000, ‘D050’),
(‘George Woltman’, ‘E00127’, 53500, ‘D101’),
(‘Adam Smith’, ‘E63535’, 18000, ‘D202’),
(‘Claire Buckman’, ‘E39876’, 27800, ‘D202’),
(‘David McClellan’, ‘E04242’, 41500, ‘D101’),
(‘Rich Holcomb’, ‘E01234’, 49500, ‘D202’),
(‘Nathan Adams’, ‘E41298’, 21900, ‘D050’),
(‘Richard Potter’, ‘E43128’, 15900, ‘D101’),
(‘David Motsinger’, ‘E27002’, 19250, ‘D202’),
(‘Tim Sampair’, ‘E03033’, 27000, ‘D101’),
(‘Kim Arlich’, ‘E10001’, 57000, ‘D190’),
(‘Timothy Grove’, ‘E16398’, 29900, ‘D190’)]
 
DefaultDict[String, [(String, String, Int, String)]] departments
L(rec) data
departments[rec[3]].append(rec)
 
V n = 3
L(department, recs) sorted(departments.items())
print(‘Department #.’.format(department))
print(‘ #<15 #<15 #<15 #<15 ’.format(‘Employee Name’, ‘Employee ID’, ‘Salary’, ‘Department’))
L(rec) sorted(recs, key' rec -> rec[2], reverse' 1B)[0 .< n]
print(‘ #<15 #<15 #<15 #<15 ’.format(rec[0], rec[1], rec[2], rec[3]))
print()</syntaxhighlight>
 
{{out}}
<pre style="height:30ex;overflow:scroll>
Department D050
Employee Name Employee ID Salary Department
John Rappl E21437 47000 D050
Nathan Adams E41298 21900 D050
 
Department D101
Employee Name Employee ID Salary Department
George Woltman E00127 53500 D101
David McClellan E04242 41500 D101
Tyler Bennett E10297 32000 D101
 
Department D190
Employee Name Employee ID Salary Department
Kim Arlich E10001 57000 D190
Timothy Grove E16398 29900 D190
 
Department D202
Employee Name Employee ID Salary Department
Rich Holcomb E01234 49500 D202
Claire Buckman E39876 27800 D202
David Motsinger E27002 19250 D202
</pre>
 
=={{header|Action!}}==
<syntaxhighlight lang="action!">DEFINE PTR="CARD"
DEFINE ENTRY_SIZE="8"
 
TYPE Employee=[
PTR name,id,dep ;CHAR ARRAY
CARD salary]
 
BYTE ARRAY data(200)
BYTE count=[0]
 
PTR FUNC GetItemAddr(INT index)
PTR addr
 
addr=data+index*ENTRY_SIZE
RETURN (addr)
 
PROC Append(CHAR ARRAY n,i CARD s CHAR ARRAY d)
Employee POINTER dst
 
dst=GetItemAddr(count)
dst.name=n
dst.id=i
dst.dep=d
dst.salary=s
count==+1
RETURN
 
PROC InitData()
Append("Tyler Bennett","E10297",32000,"D101")
Append("John Rappl","E21437",47000,"D050")
Append("George Woltman","E00127",53500,"D101")
Append("Adam Smith","E63535",18000,"D202")
Append("Claire Buckman","E39876",27800,"D202")
Append("David McClellan","E04242",41500,"D101")
Append("Rich Holcomb","E01234",49500,"D202")
Append("Nathan Adams","E41298",21900,"D050")
Append("Richard Potter","E43128",15900,"D101")
Append("David Motsinger","E27002",19250,"D202")
Append("Tim Sampair","E03033",27000,"D101")
Append("Kim Arlich","E10001",57000,"D190")
Append("Timothy Grove","E16398",29900,"D190")
RETURN
 
PROC Swap(Employee POINTER e1,e2)
PTR tmp
 
tmp=e1.name e1.name=e2.name e2.name=tmp
tmp=e1.id e1.id=e2.id e2.id=tmp
tmp=e1.dep e1.dep=e2.dep e2.dep=tmp
tmp=e1.salary e1.salary=e2.salary e2.salary=tmp
RETURN
 
PROC Sort()
INT i,j,minpos,comp
Employee POINTER e1,e2
 
FOR i=0 TO count-2
DO
minpos=i
FOR j=i+1 TO count-1
DO
e1=GetItemAddr(minpos)
e2=GetItemAddr(j)
comp=SCompare(e1.dep,e2.dep)
IF comp>0 OR comp=0 AND e1.salary<e2.salary THEN
minpos=j
FI
OD
IF minpos#i THEN
e1=GetItemAddr(minpos)
e2=GetItemAddr(i)
Swap(e1,e2)
FI
OD
RETURN
 
PROC TopRank(BYTE n)
BYTE i,c
CHAR ARRAY d
Employee POINTER e
 
i=0
WHILE i<count
DO
e=GetItemAddr(i)
IF i=0 OR SCompare(e.dep,d)#0 THEN
d=e.dep c=0
IF i>0 THEN PutE() FI
PrintF("Department %S:%E",d)
c==+1
PrintF(" %U %S %S%E",e.salary,e.id,e.name)
ELSEIF c<n THEN
c==+1
PrintF(" %U %S %S%E",e.salary,e.id,e.name)
FI
i==+1
OD
RETURN
 
PROC Main()
InitData()
Sort()
TopRank(3)
RETURN</syntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Top_rank_per_group.png Screenshot from Atari 8-bit computer]
<pre>
Department D050:
47000 E21437 John Rappl
21900 E41298 Nathan Adams
 
Department D101:
53500 E00127 George Woltman
41500 E04242 David McClellan
32000 E10297 Tyler Bennett
 
Department D190:
57000 E10001 Kim Arlich
29900 E16398 Timothy Grove
 
Department D202:
49500 E01234 Rich Holcomb
27800 E39876 Claire Buckman
19250 E27002 David Motsinger
</pre>
 
=={{header|Ada}}==
top.adb:
<langsyntaxhighlight Adalang="ada">with Ada.Containers.Vectors;
with Ada.Text_IO;
 
Line 95 ⟶ 277:
end;
end loop;
end Top;</langsyntaxhighlight>{{out}}
<pre style="height:30ex;overflow:scroll">Department D050
John Rappl | E21437 | 47000
Line 112 ⟶ 294:
 
=={{header|Aime}}==
<langsyntaxhighlight lang="aime">Add_Employee(record employees, text name, id, integer salary, text department)
{
employees[name] = list(name, id, salary, department);
Line 165 ⟶ 347:
 
0;
}</langsyntaxhighlight>Run as:
<pre>aime rcs/top_rank_per_group c N 5</pre>{{out}}
<pre style="height:30ex;overflow:scroll">Department D050
Line 184 ⟶ 366:
David Motsinger | E27002 | 19250
Adam Smith | E63535 | 18000</pre>
 
=={{header|ALGOL 68}}==
Using code from the [[Sort using a custom comparator#ALGOL 68|ALGOL 68 sample in the Sort using a custom comparator task]].
<syntaxhighlight lang="algol68">
BEGIN # show the top rank salaries per department #
# NODE to hold the employee data - will be the MODE that is sorted #
MODE SITEM = STRUCT( STRING employee name
, STRING employee id
, INT salary
, STRING department
);
# ---- begin code from the quicksort using a custom comparator task ----- #
#--- Swap function ---#
PROC swap = (REF[]SITEM array, INT first, INT second) VOID:
(
SITEM temp := array[first];
array[first] := array[second];
array[second]:= temp
);
#--- Quick sort partition arg function with custom comparision function ---#
PROC quick = (REF[]SITEM array, INT first, INT last, PROC(SITEM,SITEM)INT compare) VOID:
(
INT smaller := first + 1,
larger := last;
SITEM pivot := array[first];
WHILE smaller <= larger DO
WHILE compare(array[smaller], pivot) < 0 AND smaller < last DO
smaller +:= 1
OD;
WHILE compare( array[larger], pivot) > 0 AND larger > first DO
larger -:= 1
OD;
IF smaller < larger THEN
swap(array, smaller, larger);
smaller +:= 1;
larger -:= 1
ELSE
smaller +:= 1
FI
OD;
swap(array, first, larger);
IF first < larger-1 THEN
quick(array, first, larger-1, compare)
FI;
IF last > larger +1 THEN
quick(array, larger+1, last, compare)
FI
);
#--- Quick sort array function with custom comparison function ---#
PROC quicksort = (REF[]SITEM array, PROC(SITEM,SITEM)INT compare) VOID:
(
IF UPB array > LWB array THEN
quick(array, LWB array, UPB array, compare)
FI
);
# ==== end code from the quicksort using a custom comparator task ===== #
 
# sort comparison routine - sort ascending department, descending salary #
PROC sort by department then salary = ( SITEM a, SITEM b )INT:
IF department OF a < department OF b THEN -1
ELIF department OF a > department OF b THEN 1
ELIF salary OF a > salary OF b THEN -1
ELIF salary OF a < salary OF b THEN 1
ELSE 0
FI # sort by department then salary # ;
 
# returns s blank padded on the right to at least w characters #
PROC pad right = ( STRING s, INT w )STRING:
IF INT len = ( UPB s - LWB s ) + 1; len >= w THEN s ELSE s + ( ( w - len ) * " " ) FI;
# shows the top n ranked salaries in each department #
PROC show top rank = ( []SITEM data, INT n )VOID:
BEGIN
# copy the data and sort it #
[ LWB data : UPB data ]SITEM sorted data := data;
quicksort( sorted data, sort by department then salary );
# show the top salaries per department #
INT d pos := LWB sorted data;
WHILE d pos <= UPB sorted data DO
STRING curr department := department OF sorted data[ d pos ];
print( ( "Department: ", curr department, newline ) );
INT e count := 0;
WHILE IF e count < n THEN
print( ( " "
, employee id OF sorted data[ d pos ]
, " "
, pad right( employee name
OF sorted data[ d pos ], 24 )
, " "
, whole( salary OF sorted data[ d pos ], -6 )
, newline
)
)
FI;
e count +:= 1;
d pos +:= 1;
IF d pos > UPB sorted data
THEN FALSE
ELSE curr department = department OF sorted data[ d pos ]
FI
DO SKIP OD;
print( ( newline ) )
OD
END # show top rank # ;
 
# employee data #
[]SITEM employees = ( ( "Tyler Bennett", "E10297", 32000, "D101" )
, ( "John Rappl", "E21437", 47000, "D050" )
, ( "George Woltman", "E00127", 53500, "D101" )
, ( "Adam Smith", "E63535", 18000, "D202" )
, ( "Claire Buckman", "E39876", 27800, "D202" )
, ( "David McClellan", "E04242", 41500, "D101" )
, ( "Rich Holcomb", "E01234", 49500, "D202" )
, ( "Nathan Adams", "E41298", 21900, "D050" )
, ( "Richard Potter", "E43128", 15900, "D101" )
, ( "David Motsinger", "E27002", 19250, "D202" )
, ( "Tim Sampair", "E03033", 27000, "D101" )
, ( "Kim Arlich", "E10001", 57000, "D190" )
, ( "Timothy Grove", "E16398", 29900, "D190" )
);
# show the top two salaries by department #
show top rank( employees, 2 )
END
</syntaxhighlight>
{{out}}
<pre>
Department: D050
E21437 John Rappl 47000
E41298 Nathan Adams 21900
 
Department: D101
E00127 George Woltman 53500
E04242 David McClellan 41500
 
Department: D190
E10001 Kim Arlich 57000
E16398 Timothy Grove 29900
 
Department: D202
E01234 Rich Holcomb 49500
E39876 Claire Buckman 27800
</pre>
 
=={{header|AppleScript}}==
It looks as if this task's requirements have changed — possibly more than once — since it was first set and named. As at the end of May 2021, it specifies the return of the top N ''salaries'' in each department and makes no mention at all of any of the other employee details. This makes it easier to decide how to handle the other thing it doesn't mention: what to return when two or more people in the same department are on the same pay. The interpretation here is "top N ''discrete'' salary values" (or of course fewer if a department doesn't have that many).
 
<syntaxhighlight lang="applescript">use AppleScript version "2.3.1" -- Mac OS X 10.9 (Mavericks) or later.
use sorter : script ¬
"Custom Iterative Ternary Merge Sort" -- <www.macscripter.net/t/timsort-and-nigsort/71383/3>
 
on topNSalariesPerDepartment(employeeRecords, n)
set output to {}
set employeeCount to (count employeeRecords)
if ((employeeCount > 0) and (n > 0)) then
-- Sort a copy of the employee record list by department
-- with descending subsorts on salary.
copy employeeRecords to employeeRecords
script comparer
on isGreater(a, b)
return ((a's department > b's department) or ¬
((a's department = b's department) and (a's salary < b's salary)))
end isGreater
end script
considering numeric strings
tell sorter to sort(employeeRecords, 1, employeeCount, {comparer:comparer})
end considering
-- Initialise the output with data from the first record in the sorted list,
-- then work through the rest of the list.
set {department:previousDepartment, salary:previousSalary} to beginning of employeeRecords
set {mv, topSalaries} to {"-", {previousSalary}}
set end of output to {department:previousDepartment, salaries:topSalaries}
repeat with i from 2 to employeeCount
set {department:thisDepartment, salary:thisSalary} to item i of employeeRecords
if (thisDepartment = previousDepartment) then
if ((thisSalary < previousSalary) and ((count topSalaries) < n)) then
set end of topSalaries to thisSalary
set previousSalary to thisSalary
end if
else
-- First record of the next department.
-- Pad out the previous department's salary list if it has fewer than n entries.
repeat (n - (count topSalaries)) times
set end of topSalaries to mv
end repeat
-- Start a result record for the new department and add it to the output.
set topSalaries to {thisSalary}
set end of output to {department:thisDepartment, salaries:topSalaries}
set previousDepartment to thisDepartment
set previousSalary to thisSalary
end if
end repeat
-- Pad the last department's salary list if necessary.
repeat (n - (count topSalaries)) times
set end of topSalaries to mv
end repeat
end if
return output
end topNSalariesPerDepartment
 
on join(lst, delim)
set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to delim
set txt to lst as text
set AppleScript's text item delimiters to astid
return txt
end join
 
on task()
set employeeRecords to {¬
{|name|:"Tyler Bennett", |ID|:"E10297", salary:32000, department:"D101"}, ¬
{|name|:"John Rappl", |ID|:"E21437", salary:47000, department:"D050"}, ¬
{|name|:"George Woltman", |ID|:"E00127", salary:53500, department:"D101"}, ¬
{|name|:"Adam Smith", |ID|:"E63535", salary:18000, department:"D202"}, ¬
{|name|:"Claire Buckman", |ID|:"E39876", salary:27800, department:"D202"}, ¬
{|name|:"David McClellan", |ID|:"E04242", salary:41500, department:"D101"}, ¬
{|name|:"Rich Holcomb", |ID|:"E01234", salary:49500, department:"D202"}, ¬
{|name|:"Nathan Adams", |ID|:"E41298", salary:21900, department:"D050"}, ¬
{|name|:"Richard Potter", |ID|:"E43128", salary:15900, department:"D101"}, ¬
{|name|:"David Motsinger", |ID|:"E27002", salary:19250, department:"D202"}, ¬
{|name|:"Tim Sampair", |ID|:"E03033", salary:27000, department:"D101"}, ¬
{|name|:"Kim Arlich", |ID|:"E10001", salary:57000, department:"D190"}, ¬
{|name|:"Timothy Grove", |ID|:"E16398", salary:29900, department:"D190"}, ¬
{|name|:"Simila Pey", |ID|:"E16399", salary:29900, department:"D190"} ¬
}
set n to 4
set topSalaryRecords to topNSalariesPerDepartment(employeeRecords, n)
-- Derive a text report from the result.
set report to {"Top " & n & " salaries per department:"}
repeat with thisRecord in topSalaryRecords
set end of report to thisRecord's department & ": " & join(thisRecord's salaries, " ")
end repeat
return join(report, linefeed)
end task
 
task()</syntaxhighlight>
 
{{output}}
<syntaxhighlight lang="applescript">"Top 4 salaries per department:
D050: 47000 21900 - -
D101: 53500 41500 32000 27000
D190: 57000 29900 - -
D202: 49500 27800 19250 18000"</syntaxhighlight>
 
=={{header|Arturo}}==
 
<syntaxhighlight lang="rebol">printTopEmployees: function [count, entries][
data: read.csv.withHeaders entries
departments: sort unique map data 'row -> row\Department
loop departments 'd [
print "----------------------"
print ["department:" d]
print "----------------------"
loop first.n: count
sort.descending.by:"Salary"
select data 'row [row\Department = d] 'employee ->
print [get employee "Employee Name" "->" employee\Salary]
print ""
]
]
 
printTopEmployees 2 {
Employee Name,Employee ID,Salary,Department
Tyler Bennett,E10297,32000,D101
John Rappl,E21437,47000,D050
George Woltman,E00127,53500,D101
Adam Smith,E63535,18000,D202
Claire Buckman,E39876,27800,D202
David McClellan,E04242,41500,D101
Rich Holcomb,E01234,49500,D202
Nathan Adams,E41298,21900,D050
Richard Potter,E43128,15900,D101
David Motsinger,E27002,19250,D202
Tim Sampair,E03033,27000,D101
Kim Arlich,E10001,57000,D190
Timothy Grove,E16398,29900,D190
}</syntaxhighlight>
 
{{out}}
 
<pre>----------------------
department: D050
----------------------
John Rappl -> 47000
Nathan Adams -> 21900
 
----------------------
department: D101
----------------------
George Woltman -> 53500
David McClellan -> 41500
 
----------------------
department: D190
----------------------
Kim Arlich -> 57000
Timothy Grove -> 29900
 
----------------------
department: D202
----------------------
Rich Holcomb -> 49500
Claire Buckman -> 27800</pre>
 
=={{header|AutoHotkey}}==
<langsyntaxhighlight lang="autohotkey">Departments = D050, D101, D190, D202
StringSplit, Department_, Departments, `,, %A_Space%
 
Line 241 ⟶ 727:
Employee_%m%_Salary := Salary
Employee_%m%_Dept := Department
}</langsyntaxhighlight>{{out}}
<pre style="height:30ex;overflow:scroll">Department: D050
---------------------------
Line 265 ⟶ 751:
 
=={{header|AWK}}==
<syntaxhighlight lang="awk">
<lang AWK>
# syntax: GAWK -f TOP_RANK_PER_GROUP.AWK [n]
#
Line 311 ⟶ 797:
exit(0)
}
</syntaxhighlight>
</lang>
<p>Sample command and output:</p>
<pre>
Line 335 ⟶ 821:
=={{header|Bracmat}}==
Bracmat has no dedicated sorting functions. However, when evaluating algebraic expressions, Bracmat sorts factors in products and terms in sums. Moreover, Bracmat simplifies products by, amongst other transformations, collecting exponents of the same base into a single exponent, which is the sum of the collected exponents: <code>a^b*a^c</code> &rarr; <code>a^(b+c)</code>. This built-in behaviour is made use of in this solution.
<langsyntaxhighlight lang="bracmat"> (Tyler Bennett,E10297,32000,D101)
(John Rappl,E21437,47000,D050)
(George Woltman,E00127,53500,D101)
Line 374 ⟶ 860:
)
& toprank$(!employees.3)
& ;</langsyntaxhighlight>{{out}}
<pre style="height:30ex;overflow:scroll">Top 3 salaries per department.
Department D050:
Line 392 ⟶ 878:
 
=={{header|C}}==
<langsyntaxhighlight lang="c">#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Line 446 ⟶ 932:
top(2);
return 0;
}</langsyntaxhighlight>{{out}}
<pre>D050 47000: John Rappl
D050 21900: Nathan Adams
Line 461 ⟶ 947:
=={{header|C sharp|C#}}==
 
<langsyntaxhighlight lang="csharp">using System;
using System.Collections.Generic;
using System.Linq;
Line 530 ⟶ 1,016:
}
}
}</langsyntaxhighlight>{{out}}
<pre style="height:30ex;overflow:scroll">
Department: D101
Line 552 ⟶ 1,038:
 
=={{header|C++}}==
<langsyntaxhighlight lang="cpp">#include <string>
#include <set>
#include <list>
Line 665 ⟶ 1,151:
 
return 0;
}</langsyntaxhighlight>{{out}}
<pre style="height:30ex;overflow:scroll">In department D050
Name ID Salary Department
Line 689 ⟶ 1,175:
 
=={{header|Ceylon}}==
<langsyntaxhighlight lang="ceylon">class Employee(name, id, salary, dept) {
shared String name;
shared String id;
Line 730 ⟶ 1,216:
for (dept -> staff in employees.group(Employee.dept))
dept -> staff.sort(byDecreasing(Employee.salary)).take(n)
};</langsyntaxhighlight>
 
=={{header|Clojure}}==
 
<langsyntaxhighlight lang="lisp">(use '[clojure.contrib.seq-utils :only (group-by)])
 
(defstruct employee :Name :ID :Salary :Department)
Line 759 ⟶ 1,245:
(doseq [e (take 3 (reverse (sort-by :Salary emps)))]
(println e)))
</langsyntaxhighlight>{{out}}
<pre style="height:30ex;overflow:scroll">Department: D050
{:Name John Rappl, :ID E21437, :Salary 47000, :Department D050}
Line 777 ⟶ 1,263:
 
=={{header|Common Lisp}}==
<langsyntaxhighlight lang="lisp">(defun top-n-by-group (n data value-key group-key predicate &key (group-test 'eql))
(let ((not-pred (complement predicate))
(group-data (make-hash-table :test group-test)))
Line 810 ⟶ 1,296:
(second entry) (insert datum (second entry))))))
(dolist (datum data group-data)
(update-entry (entry (funcall group-key datum)) datum)))))</langsyntaxhighlight>
Example
<langsyntaxhighlight lang="lisp">> (defparameter *employee-data*
'(("Tyler Bennett" E10297 32000 D101)
("John Rappl" E21437 47000 D050)
Line 839 ⟶ 1,325:
D050 (2 (("Nathan Adams" E41298 21900 D050) ("John Rappl" E21437 47000 D050)))
D202 (3 (("David Motsinger" E27002 19250 D202) ("Claire Buckman" E39876 27800 D202) ("Rich Holcomb" E01234 49500 D202)))
D190 (2 (("Timothy Grove" E16398 29900 D190) ("Kim Arlich" E10001 57000 D190)))</langsyntaxhighlight>
 
=={{header|D}}==
<langsyntaxhighlight lang="d">import std.stdio, std.algorithm, std.conv, std.range;
 
struct Employee {
Line 876 ⟶ 1,362:
writefln("Department %s\n %(%s\n %)\n", dep, recs.take(n));
}
}</langsyntaxhighlight>{{out}}
<pre style="height:30ex;overflow:scroll">Department D202
Employee("Rich Holcomb", "E01234", 49500, "D202")
Line 895 ⟶ 1,381:
Employee("Nathan Adams", "E41298", 21900, "D050")</pre>
 
=={{header|DyalectDelphi}}==
{{works with|Delphi|6.0}}
{{libheader|SysUtils,StdCtrls}}
 
<lang dyalect>type Employee(name,id,salary,department)
 
<syntaxhighlight lang="Delphi">
func Employee.toString() {
 
type TEmployeeInfo = record
Name,ID: string;
Salary: double;
Dept: string;
end;
 
var EmployeeInfo: array [0..12] of TEmployeeInfo = (
(Name: 'Tyler Bennett'; ID: 'E10297'; Salary: 32000; Dept: 'D101'),
(Name: 'John Rappl'; ID: 'E21437'; Salary: 47000; Dept: 'D050'),
(Name: 'George Woltman'; ID: 'E00127'; Salary: 53500; Dept: 'D101'),
(Name: 'Adam Smith'; ID: 'E63535'; Salary: 18000; Dept: 'D202'),
(Name: 'Claire Buckman'; ID: 'E39876'; Salary: 27800; Dept: 'D202'),
(Name: 'David McClellan'; ID: 'E04242'; Salary: 41500; Dept: 'D101'),
(Name: 'Rich Holcomb'; ID: 'E01234'; Salary: 49500; Dept: 'D202'),
(Name: 'Nathan Adams'; ID: 'E41298'; Salary: 21900; Dept: 'D050'),
(Name: 'Richard Potter'; ID: 'E43128'; Salary: 15900; Dept: 'D101'),
(Name: 'David Motsinger'; ID: 'E27002'; Salary: 19250; Dept: 'D202'),
(Name: 'Tim Sampair'; ID: 'E03033'; Salary: 27000; Dept: 'D101'),
(Name: 'Kim Arlich'; ID: 'E10001'; Salary: 57000; Dept: 'D190'),
(Name: 'Timothy Grove'; ID: 'E16398'; Salary: 29900; Dept: 'D190')
);
 
 
function SalarySort(Item1, Item2: Pointer): Integer;
var Info1,Info2: TEmployeeInfo;
begin
Info1:=TEmployeeInfo(Item1^);
Info2:=TEmployeeInfo(Item2^);
Result:=AnsiCompareStr(Info1.Dept,Info2.Dept);
If Result=0 then Result:=Trunc(Info1.Salary-Info2.Salary);
end;
 
procedure ShowTopSalaries(Memo: TMemo);
var List: TList;
var Info: TEmployeeInfo;
var I: integer;
var S,OldDept: string;
 
procedure NewDepartment(Name: string);
begin
Memo.Lines.Add('');
Memo.Lines.Add('Department: '+Name);
Memo.Lines.Add('Employee Name Employee ID Salary Department');
OldDept:=Name;
end;
 
 
begin
List:=TList.Create;
try
for I:=0 to High(EmployeeInfo) do
List.Add(@EmployeeInfo[I]);
List.Sort(SalarySort);
OldDept:='';
for I:=0 to List.Count-1 do
begin
Info:=TEmployeeInfo(List[I]^);
if OldDept<>Info.Dept then NewDepartment(Info.Dept);
S:=Format('%-18S %9S %11.0m %8S',[Info.Name,Info.ID,Info.Salary,Info.Dept]);
Memo.Lines.Add(S);
end;
 
finally List.Free; end;
end;
 
 
</syntaxhighlight>
{{out}}
<pre>
Department: D050
Employee Name Employee ID Salary Dept
Nathan Adams E41298 $21,900 D050
John Rappl E21437 $47,000 D050
 
Department: D101
Employee Name Employee ID Salary Dept
Richard Potter E43128 $15,900 D101
Tim Sampair E03033 $27,000 D101
Tyler Bennett E10297 $32,000 D101
David McClellan E04242 $41,500 D101
George Woltman E00127 $53,500 D101
 
Department: D190
Employee Name Employee ID Salary Dept
Timothy Grove E16398 $29,900 D190
Kim Arlich E10001 $57,000 D190
 
Department: D202
Employee Name Employee ID Salary Dept
Adam Smith E63535 $18,000 D202
David Motsinger E27002 $19,250 D202
Claire Buckman E39876 $27,800 D202
Rich Holcomb E01234 $49,500 D202
 
Elapsed Time: 35.284 ms.
</pre>
 
=={{header|Dyalect}}==
 
<syntaxhighlight lang="dyalect">type Employee(name,id,salary,department) with Lookup
func Employee.ToString() {
"$\(this.salary) (name: \(this.name), id: \(this.id), department: \(this.department)"
}
 
constlet employees = [
Employee("Tyler Bennett","E10297",32000,"D101"),
Employee("John Rappl","E21437",47000,"D050"),
Line 918 ⟶ 1,508:
Employee("Timothy Grove","E16398",29900,"D190")
]
 
func topNSalaries(n) {
//We sort employees based on salary
employees.sortSort($1(x,y) => y.salary - $0x.salary)
let max =
const max = if n > employees.len() - 1 { employees.len() - 1 } else { n }
if n > employees.Length() - 1 {
employees.Length() - 1
} else {
n
}
for i in 0..max {
yield employees[i]
}
}
 
forvar eseq in= topNSalaries(5) {
for e in seq {
print(e)
}</langsyntaxhighlight>
 
{{out}}
Line 942 ⟶ 1,539:
 
=={{header|E}}==
<langsyntaxhighlight lang="e">/** Turn a list of arrays into a list of maps with the given keys. */
def addKeys(keys, rows) {
def res := [].diverge()
Line 980 ⟶ 1,577:
out.println()
}
}</langsyntaxhighlight>
 
Note: This uses an append-and-then-sort to maintain the list of top N; a sorted insert or a proper [[wp: selection algorithm|selection algorithm]] would be more efficient. As long as <var>N</var> is small, this does not matter much; the algorithm is O(n) with respect to the data set.{{out}}
Line 1,008 ⟶ 1,605:
=={{header|EchoLisp}}==
We use the '''sql.lib''' to select, sort and group records from the table 'emps'. The output is appended in a new table, 'high'.
<langsyntaxhighlight lang="scheme">
(lib 'struct) ;; tables are based upon structures
(lib 'sql) ;; sql-select function
Line 1,023 ⟶ 1,620:
group-by emp.dept
order-by emp.salary desc limit N into high))
</syntaxhighlight>
</lang>
{{out}}
<langsyntaxhighlight lang="scheme">
(define emps_file
'(("Tyler Bennett" E10297 32000 D101)
Line 1,065 ⟶ 1,662:
[3] D202 Rich Holcomb 49500
[4] D666 Simon Gallubert 42
</syntaxhighlight>
</lang>
 
</lang>
 
</lang>
 
=={{header|Elena}}==
ELENA 56.0x :
<langsyntaxhighlight lang="elena">import system'collections;
import system'routines;
import extensions;
Line 1,081 ⟶ 1,674:
class Employee
{
prop string Name : prop;
prop string ID : prop;
prop int Salary : prop;
prop string Department : prop;
string toPrintable()
Line 1,091 ⟶ 1,684:
.writePaddingRight(ID, 12)
.writePaddingRight(Salary.toPrintable(), 12)
.write:(Department);
}
Line 1,097 ⟶ 1,690:
{
topNPerDepartment(n)
= self.groupBy::(x => x.Department ).selectBy::(x)
{
^ new {
Line 1,103 ⟶ 1,696:
Employees
= x.orderBy::(f,l => f.Salary > l.Salary ).top(n).summarize(new ArrayList());
}
};
Line 1,127 ⟶ 1,720:
};
employees.topNPerDepartment:(2).forEach::(info)
{
console.printLine("Department: ",info.Department);
info.Employees.forEach:(printingLn);
console.writeLine:("---------------------------------------------")
};
console.readChar()
}</langsyntaxhighlight>
{{out}}
<pre>
Line 1,160 ⟶ 1,753:
=={{header|Elixir}}==
Quick implementation using piping and anonymous functions.
<langsyntaxhighlight Elixirlang="elixir">defmodule TopRank do
def per_groupe(data, n) do
String.split(data, ~r/(\n|\r\n|\r)/, trim: true)
Line 1,195 ⟶ 1,788:
Timothy Grove,E16398,29900,D190
"""
TopRank.per_groupe(data, 3)</langsyntaxhighlight>
 
{{out}}
Line 1,216 ⟶ 1,809:
 
=={{header|Erlang}}==
<langsyntaxhighlight Erlanglang="erlang"><-module( top_rank_per_group ).
 
-export( [employees/0, employees_in_department/2, highest_payed/2, task/1] ).
Line 1,255 ⟶ 1,848:
[io:fwrite( "~p ~p: ~p~n", [Department, Salery, Name]) || #employee{department=Department, salery=Salery, name=Name} <- Highest_payeds],
io:nl().
</langsyntaxhighlight>{{out}}
<pre><14> top_rank_per_group:task(2).
"D050" 53500: "George Woltman"
Line 1,270 ⟶ 1,863:
 
=={{header|F Sharp|F#}}==
<langsyntaxhighlight lang="fsharp">let data =
[
"Tyler Bennett", "E10297", 32000, "D101";
Line 1,289 ⟶ 1,882:
let topRank n =
Seq.groupBy (fun (_, _, _, d) -> d) data
|> Seq.map (snd >> Seq.sortBy (fun (_, _, s, _) -> -s) >> Seq.take n)</langsyntaxhighlight>
 
=={{header|Factor}}==
<langsyntaxhighlight lang="factor">USING: accessors assocs fry io kernel math.parser sequences
sorting ;
IN: top-rank
Line 1,333 ⟶ 1,926:
] first-n-each
nl
] assoc-each ;</langsyntaxhighlight>{{out}}
<pre style="height:30ex;overflow:scroll">
Department D101:
Line 1,355 ⟶ 1,948:
 
=={{header|Forth}}==
<syntaxhighlight lang="forth">
<lang Forth>
\ Written in ANS-Forth; tested under VFX.
\ Requires the novice package: http://www.forth.org/novice.html
Line 1,485 ⟶ 2,078:
 
test-data kill-employee
</langsyntaxhighlight>
{{out}}
<pre style="height:30ex;overflow:scroll">
Line 1,520 ⟶ 2,113:
 
=={{header|Fortran}}==
The example data can easily be declared via DATA statements, as with <langsyntaxhighlight Fortranlang="fortran"> DATA EMPLOYEE(1:3)/
1 GRIST("Tyler Bennett","E10297",32000,"D101"),
2 GRIST("John Rappl","E21437",47000,"D050"),
3 GRIST("George Woltman","E00127",53500,"D101")/
</syntaxhighlight>
</lang>
(just showing the first three), however this does not allow the preparation of the header line, because <code>GRIST("Employee Name","Employee ID","Salary","Department")</code> would be invalid since the "salary" entry is a floating-point number in the data aggregate, not text. The header line could be discarded, but this is in violation of the ideas of properly-described data files. So, the plan is to read the data from an input file containing the full example input, with its header line given special treatment. No attempt is made to detect or report improperly-formatted data. The READ statements could refer to an internally-defined block of text, but reading an actual disc file is more normal. Ad-hoc decisions are made for the size of the CHARACTER variables, that are "surely big enough" for the example data, likewise with the size of the array to hold all the records.
 
Line 1,535 ⟶ 2,128:
If the requirement had been to report the highest-ranked salary, the deed could have been done via the F90 function MAXLOC, which locates the array index of the (first-encountered?) maximum value of an array of values; further, it allows an additional MASK parameter which could be used to select only those entries having a particular "department" code. However, aside from the multiple scans that would be required for multiple departmental codes, there is the requirement for the top N salaries, and anyway, there would still be the need to identify the different departmental codes once only. Accordingly, the way ahead is the classic: sort the data and then work through the sorted sequence. Since standard Fortran provides no "sort" function in its standard libraries nor does it offer a pre-processor that might include a sort generator and the like to generate the specific code needed for a particular data aggregate and sort key specification, one must engage in some repetition. For this purpose, the "comb" sort is convenient with its code requiring just one comparison and one "swap" action, so in-line code is not troublesome. On the other hand, when dealing with compound sort keys, a three-way IF statement (or equivalent) is necessary whereby the first field of the sort key is compared with appropriate action for the < and > cases, but for the = case the comparison moves on to the second key. ''Three'' different consequences from the one comparison. Despite the deprecations of the modernisers this is still possible for numerical comparisons, but alas, character comparisons are not allowed in an arithmetic-IF statement - though one could struggle with ICHAR action. Thus, two comparisons are made where only one should suffice.
 
Finally, standard Fortran does not offer a means of receiving parameters as might be supplied when a code file is activated in a command-line environment. There may be special library routines with names such as GETARG, but they're not standard. So, a READ statement is employed. Or, one could rewrite this routine as a subroutine having one parameter so as to approximate the form of the specification more closely. Extra statements... <langsyntaxhighlight Fortranlang="fortran"> PROGRAM TOP RANK !Just do it.
CHARACTER*28 HEADING(4) !The first line is a header.
TYPE GRIST !But this is the stuff.
Line 1,603 ⟶ 2,196:
 
END !That was straightforward.
</syntaxhighlight>
</lang>
 
As ever, some tricky sizing of fields in the FORMAT statements, and a collection of ad-hoc constants. Cross-linking the integers via PARAMETER statements and the like would add a whole lot of blather, so if field sizes are changed, a fair amount of fiddling would follow. A more accomplished data processing routine would include this.
Line 1,628 ⟶ 2,221:
2 Claire Buckman E39876 27800.00 D202
3 David Motsinger E27002 19250.00 D202
</pre>
 
=={{header|FreeBASIC}}==
<syntaxhighlight lang="freebasic">#define N 3 'show the top three employees of each rank
 
'here is all the data to be read in
 
data "Tyler Bennett","E10297",32000,"D101"
data "John Rappl","E21437",47000,"D050"
data "George Woltman","E00127",53500,"D101"
data "Adam Smith","E63535",18000,"D202"
data "Claire Buckman","E39876",27800,"D202"
data "David McClellan","E04242",41500,"D101"
data "Rich Holcomb","E01234",49500,"D202"
data "Nathan Adams","E41298",21900,"D050"
data "Richard Potter","E43128",15900,"D101"
data "David Motsinger","E27002",19250,"D202"
data "Tim Sampair","E03033",27000,"D101"
data "Kim Arlich","E10001",57000,"D190"
data "Timothy Grove","E16398",29900,"D190"
 
type employee
'define a data type for employees
nm as string*32 'name
en as string*6 'employee number
sl as uinteger 'salary
dp as string*4 'department
fl as boolean 'a flag
end type
 
dim as employee emp(1 to 13)
dim as uinteger e, d, x, ce, cs
dim as string*4 dept(1 to 4) = {"D050", "D101", "D190", "D202"}
 
for e = 1 to 13
'put all the employee data into an array
read emp(e).nm
read emp(e).en
read emp(e).sl
read emp(e).dp
emp(e).fl = false
next e
 
for d = 1 to 4 'look at each department
print "Department ";dept(d);":"
for x = 1 to N 'top N employees
cs = 0
ce = 0
for e = 1 to 13 'look through employees
if emp(e).dp = dept(d) andalso emp(e).fl = false andalso emp(e).sl > cs then
emp(ce).fl = false 'unflag the previous champion so they can be found on the next pass
ce = e
cs = emp(e).sl
emp(e).fl = true 'flag this employee so that on the next pass we can get the next richest
endif
next e
if ce>0 then print emp(ce).nm;" ";emp(ce).en;" ";emp(ce).sl;" ";emp(ce).dp
next x
print
next d</syntaxhighlight>
 
{{out}}<pre>
Department D050:
John Rappl E21437 47000 D050
Nathan Adams E41298 21900 D050
 
Department D101:
George Woltman E00127 53500 D101
David McClellan E04242 41500 D101
Tyler Bennett E10297 32000 D101
 
Department D190:
Kim Arlich E10001 57000 D190
Timothy Grove E16398 29900 D190
 
Department D202:
Rich Holcomb E01234 49500 D202
Claire Buckman E39876 27800 D202
David Motsinger E27002 19250 D202
</pre>
 
=={{header|FunL}}==
<langsyntaxhighlight lang="funl">data Employee( name, id, salary, dept )
 
employees = [
Line 1,657 ⟶ 2,329:
printf( " %-16s %6s %7d\n", e.name, e.id, e.salary )
println()</langsyntaxhighlight>
{{out}}
Line 1,680 ⟶ 2,352:
 
=={{header|Go}}==
<langsyntaxhighlight lang="go">package main
 
import (
Line 1,800 ⟶ 2,472:
}
}
}</langsyntaxhighlight>
{{out|Output (with additional data demonstrating ties)}}
<pre style="height:30ex;overflow:scroll">
Line 1,823 ⟶ 2,495:
 
=={{header|Groovy}}==
<langsyntaxhighlight lang="groovy">def displayRank(employees, number) {
employees.groupBy { it.Department }.sort().each { department, staff ->
println "Department $department"
Line 1,850 ⟶ 2,522:
[Name: 'Timothy Grove', ID: 'E16398', Salary: 29900, Department: 'D190']
]
displayRank(employees, 3)</langsyntaxhighlight>{{out}}
<pre style="height:30ex;overflow:scroll">Department D050
Name ID Salary
Line 1,876 ⟶ 2,548:
====Data.List====
{{Works with|GHC|7.10.3}}
<langsyntaxhighlight lang="haskell">import Data.List (sortBy, groupBy)
 
import Text.Printf (printf)
Line 1,954 ⟶ 2,626:
putStrLn $ replicate 31 '='
mapM_ (traverse ((printf "%-16s %3s %10.2g\n" . name) <*> dep <*> sal)) $
firstN 3 dep sal employees</langsyntaxhighlight>
{{out}}
<pre>NAME DEP TIP
Line 1,976 ⟶ 2,648:
Alternatively, if we store the data in key-value maps, rather than in a cons list, we can use Map.lookup and Map.filter, Map.keys and Map.elems, to pull out the data and shape reports fairly flexibly.
 
<syntaxhighlight lang="haskell">import Data.List (intercalate, nub, sort, sortBy, transpose)
<lang Haskell>import qualified Data.Map as M
import qualified Data.Map as M
 
import Data.Maybe (fromJust)
import Data.Ord (comparing)
import Control.Monad (join)
import Data.Maybe (fromJust)
import Data.List (nub, sortBy, sort, intercalate, transpose)
 
main :: IO ()
mapNames, mapDepts :: M.Map Int String
main =
[mapNames, mapDepts] = pure readPairs <*> [nameKV, deptKV] <*> [xs]
(putStrLn . unlines) $
table
" "
( (reportLines <*> highSalaryKeys 3)
=<< (sort . nub) (M.elems mapDepts)
)
 
mapSalariesreportLines :: M.MapString -> [(Int, Int)] -> [[String]]
reportLines dept =
mapSalaries = readPairs salaryKV xs
fmap
( \(k, n) ->
[ fromJust $ M.lookup k mapNames,
dept,
show n
]
)
 
highSalaryKeys :: Int -> String -> [(Int, Int)]
highSalaryKeys n dept =
take n $
sortBy ((flip . comparing) snd) $
(,) <*> (fromJust . flip M.lookup mapSalaries) <$>
<$> M.keys (M.filter (== dept) mapDepts)
 
reportLinesmapNames, mapDepts :: StringM.Map -> [(Int, Int)] -> [[String]]
[mapNames, mapDepts] =
reportLines dept =
(readPairs <$> [nameKV, deptKV]) <*> [xs]
fmap (\(k, n) -> [fromJust $ M.lookup k mapNames, dept, show n])
 
mapSalaries :: M.Map Int Int
mapSalaries = readPairs salaryKV xs
 
xs :: [(Int, String, String, Int)]
xs =
[ (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)
]
 
readPairs ::
:: Ord k =>
=> (a1 -> (k, a)) -> [a1] -> M.Map k a
[a1] ->
readPairs f xs = M.fromList $ f <$> xs
M.Map k a
readPairs f xs = M.fromList (f <$> xs)
 
nameKV,
nameKV, deptKV :: (Int, String, String, Int) -> (Int, String)
deptKV ::
(Int, String, String, Int) -> (Int, String)
nameKV (k, _, name, _) = (k, name)
 
deptKV (k, dept, _, _) = (k, dept)
 
Line 2,043 ⟶ 2,732:
table :: String -> [[String]] -> [String]
table delim rows =
let justifyLeft c n s = take n (s ++<> replicate n c)
justifyRight c n s = drop (length s) (replicate n c ++ s)
drop
in intercalate delim <$>
transpose (length s)
(replicate n c <> s)
((fmap =<< justifyLeft ' ' . maximum . fmap length) <$> transpose rows)
in intercalate delim
 
<$> transpose
main :: IO ()
( ( fmap
main =
=<< justifyLeft ' '
(putStrLn . unlines)
. maximum
(table
" " . fmap length
(join )
(reportLines <*> highSalaryKeys 3 <$> (sorttranspose . nub) (M.elems mapDepts))))</lang>rows
)</syntaxhighlight>
{{Out}}
<pre>de Bont C.A. AB 65000
Line 2,071 ⟶ 2,761:
 
=={{header|HicEst}}==
<langsyntaxhighlight HicEstlang="hicest">CHARACTER source="Test.txt", outP='Top_rank.txt', fmt='A20,A8,i6,2x,A10'
CHARACTER name*20, employee_ID*10, department*10, temp*10
REAL :: idx(1), N_top_salaries=3
Line 2,100 ⟶ 2,790:
ENDDO
 
END</langsyntaxhighlight>{{out}}
<pre style="height:30ex;overflow:scroll">John Rappl E21437 47000 D050
Nathan Adams E41298 21900 D050
Line 2,118 ⟶ 2,808:
 
=={{header|Icon}} and {{header|Unicon}}==
<langsyntaxhighlight lang="icon">record Employee(name,id,salary,dept)
 
procedure getEmployees ()
Line 2,161 ⟶ 2,851:
every show_employee (!employeesInGroup[1:(1+min(N,*employeesInGroup))])
}
end</langsyntaxhighlight>{{out}}
<pre style="height:30ex;overflow:scroll">
$ ./top-rank-by-group 2
Line 2,196 ⟶ 2,886:
 
=={{header|IS-BASIC}}==
<langsyntaxhighlight ISlang="is-BASICbasic">100 PROGRAM "Employee.bas"(N)
110 LET NR=100:LET X=0
120 STRING NAME$(1 TO NR)*20,ID$(1 TO NR)*6,DEPT$(1 TO NR)*4
Line 2,246 ⟶ 2,936:
580 IF J<=N THEN PRINT " ";NAME$(I);TAB(23);ID$(I),SALARY(I):LET J=J+1
590 NEXT
600 END DEF</langsyntaxhighlight>
 
=={{header|J}}==
J has a rich set of primitive functions, which combine the power of an imperative language with the expressiveness of a declarative, SQL-like language:
 
<langsyntaxhighlight lang="j">NB. Dynamically generate convenience functions
('`',,;:^:_1: N=:{.Employees) =:, (_&{"1)`'' ([^:(_ -: ])L:0)"0 _~ i.# E =: {: Employees
NB. Show top six ranked employees in each dept
N , (<@:>"1@:|:@:((6 <. #) {. ] \: SALARY)/.~ DEPT) |: <"1&> E</langsyntaxhighlight>
<pre style="height:30ex;overflow:scroll">
+-----+-----+-----------------+------+
Line 2,315 ⟶ 3,005:
Named as a function where the (maximum) number of employees in each department is a parameter:
 
<langsyntaxhighlight lang="j">reportTopSalaries=: 3 :'N , (<@:>"1@:|:@:((y <. #) {. ] \: SALARY)/.~ DEPT) |: <"1&> E'</langsyntaxhighlight>{{out}}
<pre style="height:30ex;overflow:scroll">
reportTopSalaries 2
Line 2,336 ⟶ 3,026:
=={{header|Java}}==
{{works with|Java|8}}
<langsyntaxhighlight lang="java">import java.io.File;
import java.util.*;
 
Line 2,384 ⟶ 3,074:
});
}
}</langsyntaxhighlight>
 
<pre style="height:30ex;overflow:scroll">Department D050
Line 2,407 ⟶ 3,097:
 
===Iterative Solution===
<langsyntaxhighlight lang="javascript">var data = [
{name: "Tyler Bennett", id: "E10297", salary: 32000, dept: "D101"},
{name: "John Rappl", id: "E21437", salary: 47000, dept: "D050"},
Line 2,465 ⟶ 3,155:
 
top_rank(3);
</syntaxhighlight>
</lang>
{{out}}
<pre style="height:30ex;overflow:scroll">D101
Line 2,489 ⟶ 3,179:
===Map and reduce===
====ES5====
<langsyntaxhighlight lang="javascript">var collectDept = function (arrOfObj) {
var collect = arrOfObj.reduce(function (rtnObj, obj) {
if (rtnObj[obj.dept] === undefined) {
Line 2,519 ⟶ 3,209:
return list.slice(0,n);
});
};</langsyntaxhighlight>
====ES6====
By composition of generic functions:
<langsyntaxhighlight JavaScriptlang="javascript">(() => {
'use strict';
 
Line 2,679 ⟶ 3,369:
topNSalariesPerDept(3, xs)
);
})();</langsyntaxhighlight>
{{Out}}
<pre>[
Line 2,696 ⟶ 3,386:
=={{header|jq}}==
The task description invites use of the "language-native" data structure, which for jq is JSON, and so the following assumes that the file data.json contains an array of objects, each having as keys the strings on the header line. Thus, the first object in the array looks like this:
<langsyntaxhighlight lang="json"> {
"Employee Name": "Tyler Bennett",
"Employee ID": "E10297",
"Salary": "32000",
"Department": "D101"
}</langsyntaxhighlight>
===Program===
<langsyntaxhighlight lang="jq">def top_rank_per_department(n):
group_by(.Department)
| reduce .[] as $dept
Line 2,713 ⟶ 3,403:
| ($dept[0] | .Department) as $dept
| . + [ { "Department": $dept, "top_salaries": $max } ] );
</syntaxhighlight>
</lang>
 
===Example===
With the above program, the top two salaries in each dapartment can be found as shown in the following transcript:<langsyntaxhighlight lang="json">
$ jq 'top_rank_per_department(2) data.json
[
Line 2,747 ⟶ 3,437:
]
}
]</langsyntaxhighlight>
 
=={{header|Jsish}}==
Based on Javascript, imperative solution
<langsyntaxhighlight lang="javascript">#!/usr/bin/env jsish
/* Top rank per group, in Jsish */
function top_rank(n) {
Line 2,822 ⟶ 3,512:
 
=!EXPECTEND!=
*/</langsyntaxhighlight>
 
{{out}}
Line 2,848 ⟶ 3,538:
 
=={{header|Julia}}==
<langsyntaxhighlight lang="julia"># v0.6.0
 
using DataFrames
Line 2,906 ⟶ 3,596:
println("\n$cl:\n$data")
end
</syntaxhighlight>
</lang>
 
{{out}}
Line 2,946 ⟶ 3,636:
 
=={{header|Kotlin}}==
<langsyntaxhighlight lang="scala">// version 1.1.2
 
data class Employee(val name: String, val id: String, val salary: Int, val dept: String)
Line 2,976 ⟶ 3,666:
println()
}
}</langsyntaxhighlight>
 
{{out}}
Line 2,998 ⟶ 3,688:
Claire Buckman E39876 27800
</pre>
 
=={{header|Ksh}}==
<syntaxhighlight lang="ksh">
#!/bin/ksh
exec 2> /tmp/Top_rank_per_group.err
 
# Top rank per group
 
# # Variables:
#
integer TOP_NUM=2
 
typeset -T Empsal_t=(
typeset -h 'Employee Name' ename=''
typeset -h 'Employee ID' eid=''
typeset -i -h 'Employee Salary' esalary
typeset -h 'Emplyee Department' edept=''
 
function init_employee {
typeset buff ; buff="$1"
 
typeset oldIFS ; oldIFS="$IFS"
typeset arr ; typeset -a arr
IFS=\,
arr=( ${buff} )
 
_.ename="${arr[0]}"
_.eid="${arr[1]}"
_.esalary=${arr[2]}
_.edept="${arr[3]}"
 
IFS="${oldIFS}"
}
)
 
edata='Tyler Bennett,E10297,32000,D101
John Rappl,E21437,47000,D050
George Woltman,E00127,53500,D101
Adam Smith,E63535,18000,D202
Claire Buckman,E39876,27800,D202
David McClellan,E04242,41500,D101
Rich Holcomb,E01234,49500,D202
Nathan Adams,E41298,21900,D050
Richard Potter,E43128,15900,D101
David Motsinger,E27002,19250,D202
Tim Sampair,E03033,27000,D101
Kim Arlich,E10001,57000,D190
Timothy Grove,E16398,29900,D190'
 
######
# main #
######
 
# # Employee data into array of Types
#
typeset -a empsal_t # array of Type variables (objects)
integer j i=0
echo "${edata}" | while read; do
Empsal_t empsal_t[i] # Create Type (object)
empsal_t[i++].init_employee "$REPLY" # Initialize Type (object)
done
 
# # Sort the array of Type variables
#
set -a -s -A empsal_t -K edept,esalary:n:r,ename
 
# # BUG work around! duplicate the now sorted Type array and use it for output
#
sorted=$(typeset -p empsal_t) && sorted=${sorted/empsal_t/sorted} && eval ${sorted}
 
for ((i=0; i<${#sorted[*]}; i++)); do
if [[ ${sorted[i].edept} != ${prevdept} ]] || (( j < TOP_NUM )); then
[[ ${sorted[i].edept} != ${prevdept} ]] && j=0
print "${sorted[i].edept} ${sorted[i].esalary} ${sorted[i].eid} ${sorted[i].ename}"
prevdept=${sorted[i].edept}
(( j++ ))
fi
done</syntaxhighlight>
{{out}}<pre>
D050 47000 E21437 John Rappl
D050 21900 E41298 Nathan Adams
D101 53500 E00127 George Woltman
D101 41500 E04242 David McClellan
D190 57000 E10001 Kim Arlich
D190 29900 E16398 Timothy Grove
D202 49500 E01234 Rich Holcomb
D202 27800 E39876 Claire Buckman</pre>
 
=={{header|Lua}}==
<langsyntaxhighlight lang="lua">N = 2
 
lst = { { "Tyler Bennett","E10297",32000,"D101" },
Line 3,035 ⟶ 3,812:
end
print ""
end</langsyntaxhighlight>{{out}}
<pre style="height:30ex;overflow:scroll">Department: D050
John Rappl E21437 47000
Line 3,051 ⟶ 3,828:
George Woltman E00127 53500
David McClellan E04242 41500</pre>
 
=== Object-Oriented ===
<syntaxhighlight lang="lua">--Employee Class
local EmployeeMethods = {
}
local EmployeeMetamethods = {
__index=EmployeeMethods,
__tostring=function(self)
return ("%s %s %s %s"):format(self.Name,self.EmployeeId,self.Salary,self.DepartmentName)
end,
__metatable="Locked",
}
local EmployeeBase = {}
 
EmployeeBase.new = function(Name,EmployeeId,Salary,DepartmentName)
return setmetatable({
Name=Name,
EmployeeId=EmployeeId,
Salary=Salary,
DepartmentName=DepartmentName,
},EmployeeMetamethods)
end
 
--Department Class
local DepartmentMethods = {
NewEmployee=function(self,Employee)
table.insert(self.__Employees,Employee)
end,
CalculateHighestSalaries=function(self,Amount)
local Highest = {}
local EL = #self.__Employees
table.sort(self.__Employees,function(a,b)
return a.Salary > b.Salary
end)
for i=1,Amount do
if i>EL then
break
end
table.insert(Highest,self.__Employees[i])
end
return Highest
end,
}
local DepartmentMetamethods = {
__index=DepartmentMethods,
__tostring=function(self)
return ("Department %s"):format(self.Name)
end,
__metatable="Locked",
}
local DepartmentBase = {
__Departments={},
}
 
DepartmentBase.new = function(Name)
local Department = DepartmentBase.__Departments[Name]
if Department then return Department end
Department = setmetatable({
__Employees={},
Name=Name,
},DepartmentMetamethods)
DepartmentBase.__Departments[Name] = Department
return Department
end
 
--Main Program
 
local Employees = {
EmployeeBase.new("Tyler Bennett","E10297",32000,"D101"),
EmployeeBase.new("John Rappl","E21437",47000,"D050"),
EmployeeBase.new("George Woltman","E00127",53500,"D101"),
EmployeeBase.new("Adam Smith","E63535",18000,"D202"),
EmployeeBase.new("Claire Buckman","E39876",27800,"D202"),
EmployeeBase.new("David McClellan","E04242",41500,"D101"),
EmployeeBase.new("Rich Holcomb","E01234",49500,"D202"),
EmployeeBase.new("Nathan Adams","E41298",21900,"D050"),
EmployeeBase.new("Richard Potter","E43128",15900,"D101"),
EmployeeBase.new("David Motsinger","E27002",19250,"D202"),
EmployeeBase.new("Tim Sampair","E03033",27000,"D101"),
EmployeeBase.new("Kim Arlich","E10001",57000,"D190"),
EmployeeBase.new("Timothy Grove","E16398",29900,"D190"),
}
 
for _,Employee in next,Employees do
local Department = DepartmentBase.new(Employee.DepartmentName)
Department:NewEmployee(Employee)
end
 
for _,Department in next,DepartmentBase.__Departments do
local Highest = Department:CalculateHighestSalaries(2)
print(Department)
for _,Employee in next,Highest do
print("\t"..tostring(Employee))
end
end</syntaxhighlight>
{{out}}
<pre>
Department D050
John Rappl E21437 47000 D050
Nathan Adams E41298 21900 D050
Department D101
George Woltman E00127 53500 D101
David McClellan E04242 41500 D101
Department D190
Kim Arlich E10001 57000 D190
Timothy Grove E16398 29900 D190
Department D202
Rich Holcomb E01234 49500 D202
Claire Buckman E39876 27800 D202
</pre>
 
=={{header|M2000 Interpreter}}==
<syntaxhighlight lang="m2000 interpreter">
<lang M2000 Interpreter>
Module Checkit {
' erase stack of values, so we can add data
Line 3,126 ⟶ 4,014:
}
Checkit
</syntaxhighlight>
</lang>
{{out}}
<pre style="height:30ex;overflow:scroll">
Line 3,150 ⟶ 4,038:
</pre >
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<langsyntaxhighlight Mathematicalang="mathematica">InitialList ={{"Tyler Bennett","E10297",32000,"D101"},
{"John Rappl","E21437",47000,"D050"},{"George Woltman","E00127",53500,"D101"},
{"Adam Smith","E63535",18000,"D202"},{"Claire Buckman","E39876",27800,"D202"},
Line 3,164 ⟶ 4,052:
 
Scan[((Print["Department ",#[[1,4]],"\n","Employee","\t","Id","\t","Salary"]&[#])&[#];
(Scan[Print[#[[1]],"\t",#[[2]],"\t",#[[3]]]&,#] )& [#])&,TrimmedList]</langsyntaxhighlight>{{out}}
{{out}}
<pre style="height:30ex;overflow:scroll"><pre>Department D101
Employee Id Salary
Line 3,186 ⟶ 4,075:
=={{header|Nim}}==
{{trans|C}}
<langsyntaxhighlight lang="nim">import algorithm
 
type Record = tuple[name, id: string,; salary: int,; department: string]
 
var people: seq= [Record]("Tyler =Bennett", "E10297", 32000, "D101"),
@[ ("TylerJohn BennettRappl", "E10297E21437", 3200047000, "D101D050"),
("JohnGeorge RapplWoltman", "E21437E00127", 4700053500, "D050D101"),
("GeorgeAdam WoltmanSmith", "E00127E63535", 5350018000, "D101D202"),
("AdamClaire SmithBuckman", "E63535E39876", 1800027800, "D202"),
("ClaireDavid BuckmanMcClellan", "E39876E04242", 2780041500, "D202D101"),
("DavidRich McClellanHolcomb", "E04242E01234", 4150049500, "D101D202"),
("RichNathan HolcombAdams", "E01234E41298", 4950021900, "D202D050"),
("NathanRichard AdamsPotter", "E41298E43128", 2190015900, "D050D101"),
("RichardDavid PotterMotsinger", "E43128E27002", 1590019250, "D101D202"),
("DavidTim MotsingerSampair", "E27002E03033", 1925027000, "D202D101"),
("TimKim SampairArlich", "E03033E10001", 2700057000, "D101D190"),
("KimTimothy ArlichGrove", "E10001E16398", 5700029900, "D190"),]
("Timothy Grove", "E16398", 29900, "D190")]
 
proc pcmp(a, b: Record): int =
result = cmp(a.department, b.department)
if result !== 0: return
result = cmp(b.salary, a.salary)
 
proc top(n) =
sort(people, pcmp)
 
proc printTop(people: openArray[Record]; n: Positive) =
var people = sorted(people, pcmp)
var rank = 0
for i, p in people:
if i > 0 and p.department != people[i-1].department:
rank = 0
echo ""()
 
if rank < n:
echo p.department, " ", p.salary, " ", p.name
 
inc rank
 
people.printTop(2)</syntaxhighlight>
top(2)</lang>
 
Output:
{{out}}
<pre>D050 47000 John Rappl
D050 21900 Nathan Adams
Line 3,239 ⟶ 4,125:
 
=={{header|OCaml}}==
<langsyntaxhighlight lang="ocaml">open StdLabels
 
let to_string (name,_,s,_) = (Printf.sprintf "%s (%d)" name s)
Line 3,288 ⟶ 4,174:
let () =
toprank data 3;
;;</langsyntaxhighlight>{{out}}
<pre style="height:30ex;overflow:scroll">Department: D190
Kim Arlich (57000), Timothy Grove (29900)
Line 3,309 ⟶ 4,195:
Then sort each department by salaries and keep only the first n elements.
 
<langsyntaxhighlight Oforthlang="oforth">Object Class new: Employee(name, id, salary, dep)
Employee method: initialize := dep := salary := id := name ;
Line 3,335 ⟶ 4,221:
#dep employees sortBy groupWith( #dep )
map(#[ sortBy(#[ salary neg ]) left(n) ]) apply(#println) ; </langsyntaxhighlight>
 
{{out}}
Line 3,347 ⟶ 4,233:
 
=={{header|Oz}}==
<langsyntaxhighlight lang="oz">declare
%% Create a list of employee records.
Data = {Map
Line 3,392 ⟶ 4,278:
end
in
{Inspect {TopEarners Data 3}}</langsyntaxhighlight>
 
=={{header|PARI/GP}}==
{{PARI/GP select}}
<langsyntaxhighlight lang="parigp">{V=[["Tyler Bennett","E10297",32000,"D101"],
["John Rappl","E21437",47000,"D050"],
["George Woltman","E00127",53500,"D101"],
Line 3,423 ⟶ 4,309:
};
 
top(2,V)</langsyntaxhighlight>
 
=={{header|Pascal}}==
{{works with|Free_Pascal}}
{{libheader|Classes}} {{libheader|Math}}
<langsyntaxhighlight lang="pascal">program TopRankPerGroup(output);
 
uses
Line 3,497 ⟶ 4,383:
end;
end.
</langsyntaxhighlight>{{out}}
<pre style="height:30ex;overflow:scroll">% ./TopRankPerGroup
Enter the number of ranks: 3
Line 3,520 ⟶ 4,406:
 
=={{header|Perl}}==
<langsyntaxhighlight lang="perl">sub zip {
my @a = @{shift()};
my @b = @{shift()};
Line 3,566 ⟶ 4,452:
}
print "\n";
}</langsyntaxhighlight>
{{out}}
<pre>D050
Line 3,587 ⟶ 4,473:
 
=={{header|Phix}}==
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>constant N=3
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
 
<span style="color: #008080;">constant</span> <span style="color: #000000;">N</span><span style="color: #0000FF;">=</span><span style="color: #000000;">3</span>
-- Employee Name,Employee ID,Salary,Department
enum /*NAME,*/ /*ID,*/ SAL=3, DEPT=4
<span style="color: #000080;font-style:italic;">-- Employee Name,Employee ID,Salary,Department</span>
constant employees = {{"Tyler Bennett", "E10297",32000,"D101"},
<span style="color: #008080;">enum</span> <span style="color: #000080;font-style:italic;">/*NAME,*/ /*ID,*/</span> <span style="color: #000000;">SAL</span><span style="color: #0000FF;">=</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">DEPT</span><span style="color: #0000FF;">=</span><span style="color: #000000;">4</span>
{"John Rappl", "E21437",47000,"D050"},
<span style="color: #008080;">constant</span> <span style="color: #000000;">employees</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{</span><span style="color: #008000;">"Tyler Bennett"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"E10297"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">32000</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"D101"</span><span style="color: #0000FF;">},</span>
{"George Woltman", "E00127",53500,"D101"},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"John Rappl"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"E21437"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">47000</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"D050"</span><span style="color: #0000FF;">},</span>
{"Adam Smith", "E63535",18000,"D202"},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"George Woltman"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"E00127"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">53500</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"D101"</span><span style="color: #0000FF;">},</span>
{"Claire Buckman", "E39876",27800,"D202"},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Adam Smith"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"E63535"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">18000</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"D202"</span><span style="color: #0000FF;">},</span>
{"David McClellan","E04242",41500,"D101"},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Claire Buckman"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"E39876"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">27800</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"D202"</span><span style="color: #0000FF;">},</span>
{"Rich Holcomb", "E01234",49500,"D202"},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"David McClellan"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"E04242"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">41500</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"D101"</span><span style="color: #0000FF;">},</span>
{"Nathan Adams", "E41298",21900,"D050"},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Rich Holcomb"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"E01234"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">49500</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"D202"</span><span style="color: #0000FF;">},</span>
{"Richard Potter", "E43128",15900,"D101"},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Nathan Adams"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"E41298"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">21900</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"D050"</span><span style="color: #0000FF;">},</span>
{"David Motsinger","E27002",19250,"D202"},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Richard Potter"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"E43128"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">15900</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"D101"</span><span style="color: #0000FF;">},</span>
{"Tim Sampair", "E03033",27000,"D101"},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"David Motsinger"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"E27002"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">19250</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"D202"</span><span style="color: #0000FF;">},</span>
{"Kim Arlich", "E10001",57000,"D190"},
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Tim Sampair"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"E03033"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">27000</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"D101"</span><span style="color: #0000FF;">},</span>
{"Timothy Grove", "E16398",29900,"D190"}}
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Kim Arlich"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"E10001"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">57000</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"D190"</span><span style="color: #0000FF;">},</span>
 
<span style="color: #0000FF;">{</span><span style="color: #008000;">"Timothy Grove"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"E16398"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">29900</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"D190"</span><span style="color: #0000FF;">}}</span>
function by_dept_sal(integer i, integer j)
return compare(employees[i][DEPT]&-employees[i][SAL],
<span style="color: #008080;">function</span> <span style="color: #000000;">by_dept_sal</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">)</span>
employees[j][DEPT]&-employees[j][SAL])
<span style="color: #008080;">return</span> <span style="color: #7060A8;">compare</span><span style="color: #0000FF;">(</span><span style="color: #000000;">employees</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">DEPT</span><span style="color: #0000FF;">]&-</span><span style="color: #000000;">employees</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">SAL</span><span style="color: #0000FF;">],</span>
end function
<span style="color: #000000;">employees</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">][</span><span style="color: #000000;">DEPT</span><span style="color: #0000FF;">]&-</span><span style="color: #000000;">employees</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">][</span><span style="color: #000000;">SAL</span><span style="color: #0000FF;">])</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
sequence tags = custom_sort(routine_id("by_dept_sal"),tagset(length(employees)))
 
<span style="color: #004080;">sequence</span> <span style="color: #000000;">tags</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">custom_sort</span><span style="color: #0000FF;">(</span><span style="color: #000000;">by_dept_sal</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">employees</span><span style="color: #0000FF;">)))</span>
string lastdep = ""
integer dcount = 0
<span style="color: #004080;">string</span> <span style="color: #000000;">lastdep</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
printf(1,"Top %d salaries by department\n",{N})
<span style="color: #004080;">integer</span> <span style="color: #000000;">dcount</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
for i=1 to length(employees) do
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Top %d salaries by department\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">N</span><span style="color: #0000FF;">})</span>
object emp = employees[tags[i]]
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">employees</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
if emp[DEPT]!=lastdep then
<span style="color: #004080;">object</span> <span style="color: #000000;">emp</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">employees</span><span style="color: #0000FF;">[</span><span style="color: #000000;">tags</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]]</span>
lastdep = emp[DEPT]
<span style="color: #008080;">if</span> <span style="color: #000000;">emp</span><span style="color: #0000FF;">[</span><span style="color: #000000;">DEPT</span><span style="color: #0000FF;">]!=</span><span style="color: #000000;">lastdep</span> <span style="color: #008080;">then</span>
dcount = 1
<span style="color: #000000;">lastdep</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">emp</span><span style="color: #0000FF;">[</span><span style="color: #000000;">DEPT</span><span style="color: #0000FF;">]</span>
printf(1,"\n")
<span style="color: #000000;">dcount</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
else
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">)</span>
dcount += 1
<span style="color: #008080;">else</span>
end if
<span style="color: #000000;">dcount</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
if dcount<=N then
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
?emp
<span style="color: #008080;">if</span> <span style="color: #000000;">dcount</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">N</span> <span style="color: #008080;">then</span>
end if
<span style="color: #0000FF;">?</span><span style="color: #000000;">emp</span>
end for</lang>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--</syntaxhighlight>-->
{{Out}}
<pre>
Line 3,648 ⟶ 4,537:
 
=={{header|PHP}}==
<langsyntaxhighlight lang="php">$data = Array(
Array("Tyler Bennett","E10297",32000,"D101"),
Array("John Rappl","E21437",47000,"D050"),
Line 3,695 ⟶ 4,584:
echo '</pre>';
}
top_sal(3);</langsyntaxhighlight>{{out}}
<pre style="height:30ex;overflow:scroll">D050
Name ID Salary
Line 3,718 ⟶ 4,607:
David Motsinger E27002 19250
</pre>
 
=={{header|Picat}}==
<syntaxhighlight lang="picat">go =>
Emp = [
% Employee Name,Employee ID,Salary,Department
["Tyler Bennett","E10297","32000","D101"],
["John Rappl","E21437","47000","D050"],
["George Woltman","E00127","53500","D101"],
["Adam Smith","E63535","18000","D202"],
["Claire Buckman","E39876","27800","D202"],
["David McClellan","E04242","41500","D101"],
["Rich Holcomb","E01234","49500","D202"],
["Nathan Adams","E41298","21900","D050"],
["Richard Potter","E43128","15900","D101"],
["David Motsinger","E27002","19250","D202"],
["Tim Sampair","E03033","27000","D101"],
["Kim Arlich","E10001","57000","D190"],
["Timothy Grove","E16398","29900","D190"]
],
print_top_ranks(Emp,3),
nl.
 
print_top_ranks(Emp,N) =>
printf("Top %d ranks per department:\n", N),
foreach(Dept in [Dept : [_,_,_,Dept] in Emp].sort_remove_dups())
printf("Department %s\n", Dept),
Emp2 = sort_down([[Salary,Name] : [Name,_,Salary,D] in Emp, D = Dept]),
foreach({[Salary,Name],E} in zip(Emp2,1..Emp2.length), E <= N)
printf("%-20s %-10s\n", Name, Salary)
end,
nl
end.</syntaxhighlight>
 
{{out}}
<pre>Top 3 ranks per department:
Department D050
John Rappl 47000
Nathan Adams 21900
 
Department D101
George Woltman 53500
David McClellan 41500
Tyler Bennett 32000
 
Department D190
Kim Arlich 57000
Timothy Grove 29900
 
Department D202
Rich Holcomb 49500
Claire Buckman 27800
David Motsinger 19250</pre>
 
===Using data as facts===
<syntaxhighlight lang="picat">go2 =>
Emp = findall([Name,ID,Salary,Dept],emp(Name,ID,Salary,Dept)),
print_top_ranks(Emp,3),
nl.
 
emp("Tyler Bennett","E10297","32000","D101").
emp("John Rappl","E21437","47000","D050").
emp("George Woltman","E00127","53500","D101").
emp("Adam Smith","E63535","18000","D202").
emp("Claire Buckman","E39876","27800","D202").
emp("David McClellan","E04242","41500","D101").
emp("Rich Holcomb","E01234","49500","D202").
emp("Nathan Adams","E41298","21900","D050").
emp("Richard Potter","E43128","15900","D101").
emp("David Motsinger","E27002","19250","D202").
emp("Tim Sampair","E03033","27000","D101").
emp("Kim Arlich","E10001","57000","D190").
emp("Timothy Grove","E16398","29900","D190").</syntaxhighlight>
 
=={{header|PicoLisp}}==
<langsyntaxhighlight PicoLisplang="picolisp"># Employee Name, ID, Salary, Department
(de *Employees
("Tyler Bennett" E10297 32000 D101)
Line 3,746 ⟶ 4,707:
(prinl) ) ) )
 
(topEmployees 3)</langsyntaxhighlight>{{out}}
<pre style="height:30ex;overflow:scroll">Department D101:
Name ID Salary
Line 3,770 ⟶ 4,731:
 
=={{header|PL/I}}==
<langsyntaxhighlight PLlang="pl/Ii">(subrg, stringrange, stringsize):
rank: procedure options (main); /* 10 November 2013 */
 
Line 3,852 ⟶ 4,813:
end;
put skip list ('FINISHED');
end rank;</langsyntaxhighlight>{{out}}
<pre style="height:30ex;overflow:scroll">How many highest-paid employees do you want?
 
Line 3,888 ⟶ 4,849:
 
=={{header|PL/SQL}}==
<langsyntaxhighlight lang="plsql">create or replace procedure "Top rank per group"(TOP_N in pls_integer default 3) as
cursor CSR_EMP(TOP_N pls_integer) is
select case LINE
Line 3,995 ⟶ 4,956:
DBMS_OUTPUT.PUT_LINE(v_emp."Top rank per group");
end loop;
end;</langsyntaxhighlight>
 
=={{header|PowerShell}}==
<langsyntaxhighlight lang="powershell">function New-Employee ($Name, $ID, $Salary, $Department) {
New-Object PSObject `
| Add-Member -PassThru NoteProperty EmployeeName $Name `
Line 4,029 ⟶ 4,990:
} `
| Format-Table -GroupBy Department
}</langsyntaxhighlight>{{out}}
<pre style="height:30ex;overflow:scroll">PS> Get-TopRank 2
 
Line 4,061 ⟶ 5,022:
 
=={{header|Prolog}}==
<langsyntaxhighlight lang="prolog">% emp(name,id,salary,dpt)
emp('Tyler Bennett','E10297',32000,'D101').
emp('John Rappl','E21437',47000,'D050').
Line 4,113 ⟶ 5,074:
writef(' ID: %w\t%w\tSalary: %w\n', [Id,Name,Sal]),
fail.
topDeps(_).</langsyntaxhighlight>{{out}}
<pre style="height:30ex;overflow:scroll">?- topDeps(2).
Department: D101
Line 4,131 ⟶ 5,092:
 
=={{header|PureBasic}}==
<langsyntaxhighlight PureBasiclang="purebasic">Structure Employees
Name$
ID$
Line 4,188 ⟶ 5,149:
NewList MyEmployees.Employees()
 
displayTopEarners(MyEmployees(), 3)</langsyntaxhighlight>
 
'''Save this as 'DataFile.txt and let the program open this file'''<pre>
Line 4,238 ⟶ 5,199:
=={{header|Python}}==
Python 2.7/3.x compatible.
<langsyntaxhighlight lang="python">from collections import defaultdict
from heapq import nlargest
Line 4,267 ⟶ 5,228:
for rec in nlargest(N, recs, key=lambda rec: rec[-2]):
print (format % rec)
print('')</langsyntaxhighlight>{{out}}
<pre style="height:30ex;overflow:scroll">Department D050
Employee Name Employee ID Salary Department
Line 4,296 ⟶ 5,257:
Uses namedtuples for database records, and groupby builtin to group records by Department:
{{Works with|Python|3.7}}
<langsyntaxhighlight lang="python">from collections import namedtuple
from itertools import groupby
 
Line 4,329 ⟶ 5,290:
lambda record: record.Department
)
))</langsyntaxhighlight>{{out}}
<pre style="height:30ex;overflow:scroll">D050
DBRecord(Employee_Name='John Rappl', Employee_ID='E21437', Salary='47000', Department='D050')
Line 4,348 ⟶ 5,309:
=={{header|R}}==
First, read in the data.
<langsyntaxhighlight Rlang="r">dfr <- read.csv(tc <- textConnection(
"Employee Name,Employee ID,Salary,Department
Tyler Bennett,E10297,32000,D101
Line 4,362 ⟶ 5,323:
Tim Sampair,E03033,27000,D101
Kim Arlich,E10001,57000,D190
Timothy Grove,E16398,29900,D190")); close(tc)</langsyntaxhighlight>
To just return the top salary, it's very simple using tapply.
<langsyntaxhighlight Rlang="r">with(dfr, tapply(Salary, Department, max))</langsyntaxhighlight>
To return N salaries, we replace max with our own function.
<langsyntaxhighlight Rlang="r">get.top.N.salaries <- function(N)
{
with(dfr, tapply(Salary, Department,
Line 4,378 ⟶ 5,339:
}
 
get.top.N.salaries(3)</langsyntaxhighlight>
$D050
[1] 47000 21900
Line 4,392 ⟶ 5,353:
 
To return the whole record for each of the top salaries, a different tack is required.
<langsyntaxhighlight Rlang="r">get.top.N.salaries2 <- function(N)
{
#Sort data frame by Department, then by Salary
Line 4,406 ⟶ 5,367:
})
}
get.top.N.salaries2(3)</langsyntaxhighlight>{{out}}
<pre style="height:30ex;overflow:scroll"> $D050
Employee.Name Employee.ID Salary Department
Line 4,432 ⟶ 5,393:
With the dplyr package we can use group_by and top_n to select the top n records in each group.
 
<syntaxhighlight lang="r">
<lang R>
library(dplyr)
dfr %>%
group_by(Department) %>%
top_n(2, Salary)
</syntaxhighlight>
</lang>
Provides:
<pre style="height:30ex;overflow:scroll">
Line 4,453 ⟶ 5,414:
 
=={{header|Racket}}==
<langsyntaxhighlight Racketlang="racket">#lang racket
 
(struct employee (name id salary dept))
Line 4,484 ⟶ 5,445:
(employee-name e)
(employee-id e))))
</langsyntaxhighlight>{{out}}
<pre style="height:30ex;overflow:scroll">Department D101:
$53500: George Woltman (E00127)
Line 4,506 ⟶ 5,467:
This program also makes heavy use of method calls that start with dot. In Raku this means a method call on the current topic, <tt>$_</tt>, which is automatically set by any <tt>for</tt> or <tt>map</tt> construct that doesn't declare an explicit formal parameter on its closure.
 
<syntaxhighlight lang="raku" perl6line>my @data = do for q:to/---/.lines -> $line {
E10297 32000 D101 Tyler Bennett
E21437 47000 D050 John Rappl
Line 4,534 ⟶ 5,495:
say .< Dept Id Salary Name > for @es[^$N]:v;
}
}</langsyntaxhighlight>{{out}}
<pre style="height:30ex;overflow:scroll">
D050 E21437 47000 John Rappl
Line 4,552 ⟶ 5,513:
=={{header|REXX}}==
===version 1===
<langsyntaxhighlight lang="rexx">/*REXX program displays the top N salaries in each department (internal table). */
parse arg topN . /*get optional # for the top N salaries*/
if topN=='' | topN=="," then topN= 1 /*Not specified? Then use the default.*/
Line 4,588 ⟶ 5,549:
dept.h= /*make sure we see the employee again. */
end /*topN*/
end /*dep*/ /*stick a fork in it, we're all done. */</langsyntaxhighlight>
{{out|output|text=&nbsp; when using the input: &nbsp; &nbsp; <tt> 2 </tt>}}
<pre>
Line 4,635 ⟶ 5,596:
 
===version 2===
<langsyntaxhighlight lang="rexx">/* REXX ---------------------------------------------------------------
* 12.02.2014 Walter Pachl
*--------------------------------------------------------------------*/
Line 4,709 ⟶ 5,670:
exit: Say arg(1)
help: Say 'Syntax: rexx topsal [topn]'
Exit</langsyntaxhighlight>
'''output'''
<pre>13 employees, 4 departments: D101 D050 D202 D190
Line 4,728 ⟶ 5,689:
 
=={{header|Ring}}==
<langsyntaxhighlight lang="ring">
# Project : Top rank per group
 
Line 4,788 ⟶ 5,749:
ok
next
</syntaxhighlight>
</lang>
Output:
<pre>
Line 4,824 ⟶ 5,785:
Without much thought to report formatting:
{{works with|Ruby|2.2+}}
<langsyntaxhighlight lang="ruby">require "csv"
 
data = <<EOS
Line 4,856 ⟶ 5,817:
end
 
show_top_salaries_per_group(data, 3)</langsyntaxhighlight>
 
{{out}}
Line 4,880 ⟶ 5,841:
 
=={{header|Run BASIC}}==
<langsyntaxhighlight lang="runbasic">perSal$ = "Tyler Bennett,E10297,32000,D101
John Rappl,E21437,47000,D050;
George Woltman,E00127,53500,D101
Line 4,918 ⟶ 5,879:
end if
print word$(depSal$(i),1,",");chr$(9);word$(depSal$(i),2,",");chr$(9);word$(depSal$(i),3,",")
next i</langsyntaxhighlight>{{out}}
<pre style="height:30ex;overflow:scroll">Employee Name ID Salary
 
Line 4,949 ⟶ 5,910:
The implementation counts with ties.
 
<langsyntaxhighlight Rustlang="rust">#[derive(Debug)]
struct Employee<S> {
// Allow S to be any suitable string representation
Line 5,041 ⟶ 6,002:
 
Ok(())
}</langsyntaxhighlight>
 
{{out}}
Line 5,067 ⟶ 6,028:
=={{header|Scala}}==
===Application idiomatic version===
<langsyntaxhighlight lang="scala">import scala.io.Source
import scala.language.implicitConversions
import scala.language.reflectiveCalls
Line 5,124 ⟶ 6,085:
.map(_.toString).mkString("\t", "\n\t", ""))
}
}</langsyntaxhighlight>{{out}}
<pre style="height:30ex;overflow:scroll">Reporting top 3 salaries in each department.
 
Line 5,147 ⟶ 6,108:
===using SLICK ORM===
{{libheader|H2 Database Engine}} Version 1.3.1
<langsyntaxhighlight lang="scala">import scala.slick.driver.H2Driver.simple._
import scala.slick.lifted.ProvenShape
 
Line 5,298 ⟶ 6,259:
plainQuery.foreach(println(_))
} // session
} // TopNrankSLICK</langsyntaxhighlight>
{{out}}
<pre style="height:30ex;overflow:scroll">Tot.15 Employees in 4 deps.Avg salary: 33336.67
Line 5,333 ⟶ 6,294:
=={{header|Scheme}}==
{{works with|Gauche Scheme}}
<langsyntaxhighlight Schemelang="scheme">(use gauche.record)
 
;; This will let us treat a list as though it is a structure (record).
Line 5,389 ⟶ 6,350:
(for-each
(pa$ print-record col-widths)
(take* matches n))))))</langsyntaxhighlight>
<b>Testing:</b>
<pre>
Line 5,434 ⟶ 6,395:
=={{header|Sidef}}==
{{trans|Perl}}
<langsyntaxhighlight lang="ruby">var data = <<'EOF'.lines.map{ <name id salary dept> ~Z .split(',') -> flat.to_h }
Tyler Bennett,E10297,32000,D101
John Rappl,E21437,47000,D050
Line 5,460 ⟶ 6,421:
}
print "\n"
}</langsyntaxhighlight>
{{out}}
<pre>
Line 5,486 ⟶ 6,447:
The following [[SMEQL]] example returns the top 6 earners in each department based on this table schema:
 
<langsyntaxhighlight lang="smeql">table: Employees
----------------
empID
dept
empName
salary</langsyntaxhighlight>
Source Code:
<langsyntaxhighlight lang="smeql">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)</langsyntaxhighlight>
 
Note: Since SMEQL is a query language, it has no built-in I/O capability to prompt the user for the threshold number ("6" in this example). However, it would be possible to retrieve the threshold from another table, but would make the example a bit confusing. In practice, an application language would most likely pass the value to it as a parameter.
 
=={{header|SQL}}==
<langsyntaxhighlight lang="sql">create table EMP
(
EMP_ID varchar2(6 char),
Line 5,538 ⟶ 6,499:
insert into EMP (EMP_ID, EMP_NAME, DEPT_ID, SALARY)
values ('E16400','Timothy Grive','D190',29900);
COMMIT;</langsyntaxhighlight>
<langsyntaxhighlight lang="sql">select case LINE
when 10 then
'Tot.' || LPAD(POPULATION, 2) || ' Employees in ' || TIE_COUNT ||
Line 5,632 ⟶ 6,593:
where EMP4.DEPT_ID = EMP3.DEPT_ID
and EMP4.SALARY >= EMP3.SALARY))
order by DEPT_ID ,LINE ,SALARY desc, EMP_ID;</langsyntaxhighlight>{{out}}
<pre style="height:30ex;overflow:scroll">Tot.15 employees in 4 deps.Avg salary: 33336.67
-
Line 5,665 ⟶ 6,626:
 
Since there is no requirement for the layout - using the data from the table above
<langsyntaxhighlight lang="sql">WITH ranked_emp AS (
SELECT emp_name
,dept_id
Line 5,678 ⟶ 6,639:
FROM ranked_emp
WHERE ranking <= 2
ORDER BY dept_id, ranking;</langsyntaxhighlight>
 
<pre style="height:30ex;overflow:scroll">
Line 5,696 ⟶ 6,657:
=={{header|Stata}}==
The following shows the top k salaries. If there are less than k employees in a department, this will print all salaries.
<langsyntaxhighlight lang="stata">import delimited employees.csv
local k 2
bysort department (salary): list salary if _N-_n<`k'</langsyntaxhighlight>
 
=={{header|Swift}}==
 
<langsyntaxhighlight Swiftlang="swift">struct Employee {
var name: String
var id: String
Line 5,747 ⟶ 6,708:
 
print("\(dept)'s highest paid employees are: \n\t\(employeeString)")
}</langsyntaxhighlight>
 
{{out}}
Line 5,768 ⟶ 6,729:
=={{header|Tcl}}==
{{works with|Tcl|8.5}}
<langsyntaxhighlight lang="tcl">package require Tcl 8.5
 
set text {Tyler Bennett,E10297,32000,D101
Line 5,801 ⟶ 6,762:
}
 
top_n_salaries 3 $data</langsyntaxhighlight>{{out}}
<pre style="height:30ex;overflow:scroll">Department D101
George Woltman E00127 53500
Line 5,825 ⟶ 6,786:
Version using built-in database-like functionality.
 
<langsyntaxhighlight lang="scheme">#lang transd
 
#lang transd
 
MainModule: {
tabletbl : String(
`EmployeeName,@key_EmployeeIDEmployeeID,Salary:Int,Department
"Tyler Bennett", " E10297",32000,"D101"
"John Rappl", " E21437",47000,"D050"
"George Woltman", " E00127",53500,"D101"
"Adam Smith", " E63535",18000,"D202"
"Claire Buckman", " E39876",27800,"D202"
"David McClellan","E04242",41500,"D101"
"Rich Holcomb", " E01234",49500,"D202"
"Nathan Adams", " E41298",21900,"D050"
"Richard Potter", " E43128",15900,"D101"
"David Motsinger","E27002",19250,"D202"
"Tim Sampair", " E03033",27000,"D101"
"Kim Arlich", " E10001",57000,"D190"
"Timothy Grove", " E16398",29900,"D190"`),
 
N: 2,
_start: (λ (with base TSDBase()
(with tabl Table()
(load-table base table)
(buildload-indextable basetabl "Department"tbl)
(with rows (tsdbuild-queryindex basetabl select ["Department"] distinct)
(with rows (fortsd-query row in rowstabl do
(with recs (tsd-query base select: all["Department"]
as: where (lambda Department [[String()]] (eq:distinct sortby: "Department" (get row 0)))
(for row in rows do
sortby "Salary" desc limit N)
(for rec inwith recs do (textouttsd-query rectabl "\n")))))
select: all
))
as: [[String(), String(), Int(), String()]]
}</lang>{{out}}
satisfying: (lambda Department String()
(eq Department (get row 0)))
sortby: "Salary" :desc
limit: N)
(for rec in recs do (textout rec "\n")))))))
}</syntaxhighlight>{{out}}
<pre>
[D050, E21437, John Rappl, 47000]
[D050, E41298, Nathan Adams, 21900]
[D101, E00127, George Woltman, 53500]
[D101, E04242, David McClellan, 41500]
Line 5,864 ⟶ 6,833:
[D202, E01234, Rich Holcomb, 49500]
[D202, E39876, Claire Buckman, 27800]
[D050, E21437, John Rappl, 47000]
[D050, E41298, Nathan Adams, 21900]
</pre>
 
Version using untyped vectors.
<langsyntaxhighlight lang="scheme">
#lang transd
 
 
MainModule: {
tbl : String(
`"Tyler Bennett", "E10297",32000,"D101"
"John Rappl", "E21437",47000,"D050"
"George Woltman", "E00127",53500,"D101"
"Adam Smith", "E63535",18000,"D202"
"Claire Buckman", "E39876",27800,"D202"
"David McClellan", "E04242",41500,"D101"
"Rich Holcomb", "E01234",49500,"D202"
"Nathan Adams", "E41298",21900,"D050"
"Richard Potter", "E43128",15900,"D101"
"David Motsinger", "E27002",19250,"D202"
"Tim Sampair", "E03033",27000,"D101"
"Kim Arlich", "E10001",57000,"D190"
"Timothy Grove", "E16398",29900,"D190"`),
 
Record : typealias(Tuple<String String Int String>()),
N: 2,
curN: 0,
dep: String(),
deps: Index( <String( ) Int>() ),
_start: (λ
(with recs Vector<Record>( untypedTable tbl "," "\n" )
res Vector<Record>( UntypedVector() )
(sort recs Range(-1 0)
(lambda l Record() r Record() -> Bool()
(ret (less (get l 2) (get r 2)))))
 
(sortfor el in recs descdo
(lambda= ldep UntypedVector()get rel UntypedVector(3) -> Bool()
(= curN (ret (less<Int>snd (get-s l 2) (getdeps rdep 2))0)))
(if (< curN N) (add res el) (set deps dep (+ curN 1)))
)
 
(forsort rec in Range(recs dores
(lambda l Record(=) depr Record(get) @it-> 3Bool())
(= curNret (sndless (get-s depsl 3) (get depr 03)))))
(if (< curN N) (add res @it) (set deps dep (+ curN 1))))
-> Null()) do null )
 
(sort res asc
(lambda l UntypedVector() r UntypedVector() -> Bool()
(ret (less<String> (get l 3) (get r 3)))))
 
(for i in res do (textout i "\n"))
))
)
}
</langsyntaxhighlight>{{out}}
<pre>
[[John Rappl, E21437, 47000, D050]]
[[Nathan Adams, E41298, 21900, D050]]
[[George Woltman, E00127, 53500, D101]]
[[David McClellan, E04242, 41500, D101]]
[[Kim Arlich, E10001, 57000, D190]]
[[Timothy Grove, E16398, 29900, D190]]
[[Rich Holcomb, E01234, 49500, D202]]
[[Claire Buckman, E39876, 27800, D202]]
</pre>
 
=={{header|TUSCRIPT}}==
<langsyntaxhighlight lang="tuscript">$$ MODE TUSCRIPT
MODE DATA
$$ SET dates=*
Line 5,974 ⟶ 6,939:
PRINT " "
ENDLOOP
ENDCOMPILE</langsyntaxhighlight>{{out}}
<pre style='height:30ex;overflow:scroll'>
Department D050
Line 6,014 ⟶ 6,979:
The data is in a file, exactly as given in the problem. Parameter N is accepted from command line.
 
<langsyntaxhighlight lang="txr">@(next :args)
@{n-param}
@(next "top-rank-per-group.dat")
Line 6,036 ⟶ 7,001:
@ (end)
@ (end)
@(end)</langsyntaxhighlight>{{out}}
<pre style="height:30ex;overflow:scroll">Department: D101
George Woltman (E00127) $ 53500
Line 6,056 ⟶ 7,021:
Descend into argument list:
 
<syntaxhighlight lang ="txr">@(next :args)</langsyntaxhighlight>
 
Collect first argument as <code>n-param</code> variable:
 
<syntaxhighlight lang ="txr">@{n-param}</langsyntaxhighlight>
 
Drill into data file:
 
<langsyntaxhighlight lang="txr">@(next "top-rank-per-group.dat")</langsyntaxhighlight>
 
Match header exactly:
 
<langsyntaxhighlight lang="txr">Employee Name,Employee ID,Salary,Department</langsyntaxhighlight>
 
Now iterate over the data, requiring a variable called <code>record</code> to be bound in each iteration, and suppress all other variables from emerging. In the body of the collect, bind four variables. Then use these four variables to create a four-element list which is bound to the variable <code>record</code>. The <code>int-str</code> function converts the textual variable <code>salary</code> to an integer:
 
<langsyntaxhighlight lang="txr">@(collect :vars (record))
@name,@id,@salary,@dept
@(bind record (@(int-str salary) dept name id))
@(end)
</syntaxhighlight>
</lang>
 
Next, we bind five variables to the output of some TXR Lisp code, which will return five lists:
 
<langsyntaxhighlight lang="txr">@(bind (dept salary dept2 name id)
@(let* ((n (int-str n-param))
(dept-hash [group-by second record :equal-based])
Line 6,086 ⟶ 7,051:
(ranked (collect-each ((rec (hash-values dept-hash)))
[apply mapcar list [[sort rec > first] 0..n]])))
(cons dept [apply mapcar list ranked])))</langsyntaxhighlight>
 
This code binds some successive variables. <code>n</code> is an integer conversion of the command line argument.
Line 6,097 ⟶ 7,062:
The reason for these transpositions is to convert the data into individual nested lists, once for each field. This is the format needed by the TXR <code>@(output)</code> clause:
 
<langsyntaxhighlight lang="txr">@(output)
@ (repeat)
Department: @dept
Line 6,104 ⟶ 7,069:
@ (end)
@ (end)
@(end)</langsyntaxhighlight>
 
Here, all these variables are individual lists. The <code>dept</code> variable is a flat list; one nesting of <code>@(repeat)</code> iterates over it. The other variables are nested lists; a nested repeat drills into these.
Line 6,114 ⟶ 7,079:
The output is identical to the previous version.
 
<langsyntaxhighlight lang="txr">@(next :args)
@{n-param}
@(next "top-rank-per-group.dat")
Line 6,131 ⟶ 7,096:
(put-line `Department: @d`)
(each ((r dept-recs))
(put-line ` @{r[2] 15} (@{r[3]}) $@{r[0] -6}`)))))</langsyntaxhighlight>
 
=={{header|Ursala}}==
Line 6,137 ⟶ 7,102:
sort each partition descending by the second to last, take the first
n strings in each partition, and display the list of them in a reasonably understandable form.
<langsyntaxhighlight Ursalalang="ursala">#import std
#import nat
 
Line 6,162 ⟶ 7,127:
#show+
 
main = top3 data</langsyntaxhighlight>{{out}}
<pre style="height:30ex;overflow:scroll">D190
Kim Arlich,E10001,57000
Line 6,183 ⟶ 7,148:
=={{header|VBA}}==
Creating an Excel pivot table to display the top n salaried employees per department. Data is read from a file.
<langsyntaxhighlight lang="vb">Private Sub top_rank(filename As String, n As Integer)
Workbooks.OpenText filename:=filename, Comma:=True
Dim ws As Worksheet
Line 6,219 ⟶ 7,184:
Public Sub main()
top_rank filename:="D:\data.txt", n:=3
End Sub</langsyntaxhighlight>
 
=={{header|Wren}}==
Line 6,227 ⟶ 7,192:
{{libheader|Wren-seq}}
{{libheader|Wren-fmt}}
<langsyntaxhighlight ecmascriptlang="wren">import "./dynamic" for Tuple
import "./sort" for Sort, Cmp
import "./seq" for Lst
import "./fmt" for Fmt
 
var Employee = Tuple.create("Employee", ["name", "id", "salary", "dept"])
Line 6,264 ⟶ 7,229:
topRanked.each { |e| Fmt.print("$-15s $s $d", e.name, e.id, e.salary) }
System.print()
}</langsyntaxhighlight>
 
{{out}}
Line 6,285 ⟶ 7,250:
Rich Holcomb E01234 49500
Claire Buckman E39876 27800
</pre>
 
=={{header|XPL0}}==
<syntaxhighlight lang="xpl0">proc Sort(Array, Field, Size); \Sort Array in descending order by Field
int Array, Field, Size, I, J, T;
[for J:= Size-1 downto 0 do
for I:= 0 to J-1 do
if Array(I,Field) < Array(I+1,Field) then
[T:= Array(I); Array(I):= Array(I+1); Array(I+1):= T];
];
 
int Data, I, I0, Dept, N, Cnt;
[Data:=[["Tyler Bennett", "E10297", 32000, 101],
["John Rappl", "E21437", 47000, 050],
["George Woltman", "E00127", 53500, 101],
["Adam Smith", "E63535", 18000, 202],
["Claire Buckman", "E39876", 27800, 202],
["David McClellan", "E04242", 41500, 101],
["Rich Holcomb", "E01234", 49500, 202],
["Nathan Adams", "E41298", 21900, 050],
["Richard Potter", "E43128", 15900, 101],
["David Motsinger", "E27002", 19250, 202],
["Tim Sampair", "E03033", 27000, 101],
["Kim Arlich", "E10001", 57000, 190],
["Timothy Grove", "E16398", 29900, 190],
[0, 0, 0, 000]]; \sentinel
I:= 0; \find number of employees = Data size
while Data(I,0) # 0 do I:= I+1;
Sort(Data, 3, I); \sort by department field (3)
I:= 0; \sort by salary within each department
while Data(I,0) do
[Dept:= Data(I,3);
I0:= I;
repeat I:= I+1 until Data(I,3) # Dept;
Sort(@Data(I0), 2, I-I0);
];
N:= IntIn(0); \get parameter
I:= 0;
loop [Dept:= Data(I,3); \for each department
Text(0, "Department D");
if Dept < 100 then ChOut(0, ^0); IntOut(0, Dept); Text(0, ":^m^j");
Cnt:= 0;
loop [if Cnt >= N then
while Data(I,3) = Dept do I:= I+1; \skip any remaining
if Data(I,3) # Dept then quit;
IntOut(0, Data(I,2)); Text(0, " "); \salary
Text(0, Data(I,1)); Text(0, " "); \ID
Text(0, Data(I,0)); CrLf(0); \name
Cnt:= Cnt+1;
I:= I+1;
];
if Data(I,0) = 0 then quit;
];
]</syntaxhighlight>
 
{{out}}
<pre>
3
Department D202:
49500 E01234 Rich Holcomb
27800 E39876 Claire Buckman
19250 E27002 David Motsinger
Department D190:
57000 E10001 Kim Arlich
29900 E16398 Timothy Grove
Department D101:
53500 E00127 George Woltman
41500 E04242 David McClellan
32000 E10297 Tyler Bennett
Department D050:
47000 E21437 John Rappl
21900 E41298 Nathan Adams
</pre>
 
=={{header|zkl}}==
This reads a data file, the contents of which are as given by the task description (minus the header). To protect privacy, identifying information has been stripped from the output (aka laziness enhanced coding).
<langsyntaxhighlight lang="zkl">fcn setAppend(d,[(key,data)]){ d[key]=d.find(key,T).append(data) } //-->(key,(data,data...))
 
fcn topNsalaries(n){
Line 6,302 ⟶ 7,339:
"%s: %s".fmt(d,ss.concat(",")).println();
}
}(3);</langsyntaxhighlight>
{{out}}
<pre>
9,476

edits