Top rank per group: Difference between revisions

m
m (syntax highlighting fixup automation)
m (→‎{{header|Wren}}: Minor tidy)
 
(6 intermediate revisions by 4 users not shown)
Line 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 for these 'use' commands!.
use sorter : script ¬
use sorter : script "Custom Iterative Ternary Merge Sort" -- <https://macscripter.net/viewtopic.php?pid=194430#p194430>
"Custom Iterative Ternary Merge Sort" -- <www.macscripter.net/t/timsort-and-nigsort/71383/3>
 
on topNSalariesPerDepartment(employeeRecords, n)
Line 377 ⟶ 519:
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.
-- 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)))¬
((a's department = b's department) and (a's salary < b's salary)))
end isGreater
end script
Line 388 ⟶ 532:
end considering
-- Initialise the output with data from the first record in the sorted list, then work through the rest of the list.
-- then work through the rest of the list.
set {department:previousDepartment, salary:previousSalary} to beginning of employeeRecords
set {padValuemv, topSalaries, counter} to {missing value"-", {previousSalary}, 1}
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 is= previousDepartment) then
if ((thisSalary < previousSalary) and ((count topSalaries) < n)) then
-- Another record from the same department. Include its salary in the output if different from
-- the previous one's and if fewer than n salaries from the department have been included so far.
if ((thisSalary < previousSalary) and (counter < n)) then
set end of topSalaries to thisSalary
set counter to counter + 1
set previousSalary to thisSalary
end if
else
-- First record of the next department.
-- Pad out the previous department's salary list with missing values if it has fewer than n entries.
repeat (n - counter(count topSalaries)) times
set end of topSalaries to padValuemv
end repeat
-- Start a result record for the new department and add it to the output.
set topSalaries to {thisSalary}
set counter to 1
set end of output to {department:thisDepartment, salaries:topSalaries}
set previousDepartment to thisDepartment
Line 417 ⟶ 558:
end repeat
-- Pad the last department's salary list if necessary.
repeat (n - counter(count topSalaries)) times
set end of topSalaries to padValuemv
end repeat
end if
Line 425 ⟶ 566:
end topNSalariesPerDepartment
 
on demojoin(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"}, ¬
Line 444 ⟶ 593:
set n to 4
set topSalaryRecords to topNSalariesPerDepartment(employeeRecords, n)
--> eg. {{department:"D050", salaries:{47000, 21900, missing value, missing value}}, … }
-- Derive a text report from the result.
set report to {"Top " & n & " salaries per department:"}
set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to " "
repeat with thisRecord in topSalaryRecords
set end of report to thisRecord's department & ": " & join(thisRecord's salaries, " ")
set i to n
repeat while (item i of thisRecord's salaries is missing value)
set item i of thisRecord's salaries to "-"
set i to i - 1
end repeat
set end of report to thisRecord's department & ": " & thisRecord's salaries
end repeat
setreturn AppleScript's text item delimiters tojoin(report, linefeed)
end task
set report to report as text
set AppleScript's text item delimiters to astid
return report
end demo
 
demotask()</syntaxhighlight>
 
{{output}}
Line 1,242 ⟶ 1,380:
Employee("John Rappl", "E21437", 47000, "D050")
Employee("Nathan Adams", "E41298", 21900, "D050")</pre>
 
=={{header|Delphi}}==
{{works with|Delphi|6.0}}
{{libheader|SysUtils,StdCtrls}}
 
 
<syntaxhighlight lang="Delphi">
 
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}}==
Line 1,423 ⟶ 1,665:
 
=={{header|Elena}}==
ELENA 56.0x :
<syntaxhighlight lang="elena">import system'collections;
import system'routines;
Line 1,432 ⟶ 1,674:
class Employee
{
prop string Name : prop;
prop string ID : prop;
prop int Salary : prop;
prop string Department : prop;
string toPrintable()
Line 1,442 ⟶ 1,684:
.writePaddingRight(ID, 12)
.writePaddingRight(Salary.toPrintable(), 12)
.write:(Department);
}
Line 1,448 ⟶ 1,690:
{
topNPerDepartment(n)
= self.groupBy::(x => x.Department ).selectBy::(x)
{
^ new {
Line 1,454 ⟶ 1,696:
Employees
= x.orderBy::(f,l => f.Salary > l.Salary ).top(n).summarize(new ArrayList());
}
};
Line 1,478 ⟶ 1,720:
};
employees.topNPerDepartment:(2).forEach::(info)
{
console.printLine("Department: ",info.Department);
info.Employees.forEach:(printingLn);
console.writeLine:("---------------------------------------------")
};
Line 6,950 ⟶ 7,192:
{{libheader|Wren-seq}}
{{libheader|Wren-fmt}}
<syntaxhighlight lang="ecmascriptwren">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"])
9,476

edits