Top rank per group: Difference between revisions

Content added Content deleted
m (syntax highlighting fixup automation)
m (→‎{{header|AppleScript}}: New sort handler URL, tidy-up.)
Line 370: Line 370:
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).
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!
<syntaxhighlight lang="applescript">use AppleScript version "2.3.1" -- Mac OS X 10.9 (Mavericks) or later.
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)
on topNSalariesPerDepartment(employeeRecords, n)
Line 377: Line 378:
set employeeCount to (count employeeRecords)
set employeeCount to (count employeeRecords)
if ((employeeCount > 0) and (n > 0)) then
if ((employeeCount > 0) and (n > 0)) then
-- Sort a copy of the employee record list by department with descending subsorts on salary.
-- Sort a copy of the employee record list by department
-- with descending subsorts on salary.
copy employeeRecords to employeeRecords
copy employeeRecords to employeeRecords
script comparer
script comparer
on isGreater(a, b)
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)))
return ((a's department > b's department) or ¬
((a's department = b's department) and (a's salary < b's salary)))
end isGreater
end isGreater
end script
end script
Line 388: Line 391:
end considering
end considering
-- Initialise the output with data from the first record in the sorted list, then work through the rest of the list.
-- 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 {department:previousDepartment, salary:previousSalary} to beginning of employeeRecords
set {padValue, topSalaries, counter} to {missing value, {previousSalary}, 1}
set {mv, topSalaries} to {"-", {previousSalary}}
set end of output to {department:previousDepartment, salaries:topSalaries}
set end of output to {department:previousDepartment, salaries:topSalaries}
repeat with i from 2 to employeeCount
repeat with i from 2 to employeeCount
set {department:thisDepartment, salary:thisSalary} to item i of employeeRecords
set {department:thisDepartment, salary:thisSalary} to item i of employeeRecords
if (thisDepartment is previousDepartment) then
if (thisDepartment = 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 end of topSalaries to thisSalary
set counter to counter + 1
set previousSalary to thisSalary
set previousSalary to thisSalary
end if
end if
else
else
-- First record of the next department.
-- First record of the next department.
-- Pad the previous department's salary list with missing values if it has fewer than n entries.
-- Pad out the previous department's salary list if it has fewer than n entries.
repeat (n - counter) times
repeat (n - (count topSalaries)) times
set end of topSalaries to padValue
set end of topSalaries to mv
end repeat
end repeat
-- Start a result record for the new department and add it to the output.
-- Start a result record for the new department and add it to the output.
set topSalaries to {thisSalary}
set topSalaries to {thisSalary}
set counter to 1
set end of output to {department:thisDepartment, salaries:topSalaries}
set end of output to {department:thisDepartment, salaries:topSalaries}
set previousDepartment to thisDepartment
set previousDepartment to thisDepartment
Line 417: Line 417:
end repeat
end repeat
-- Pad the last department's salary list if necessary.
-- Pad the last department's salary list if necessary.
repeat (n - counter) times
repeat (n - (count topSalaries)) times
set end of topSalaries to padValue
set end of topSalaries to mv
end repeat
end repeat
end if
end if
Line 425: Line 425:
end topNSalariesPerDepartment
end topNSalariesPerDepartment


on demo()
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 {¬
set employeeRecords to {¬
{|name|:"Tyler Bennett", |ID|:"E10297", salary:32000, department:"D101"}, ¬
{|name|:"Tyler Bennett", |ID|:"E10297", salary:32000, department:"D101"}, ¬
Line 444: Line 452:
set n to 4
set n to 4
set topSalaryRecords to topNSalariesPerDepartment(employeeRecords, n)
set topSalaryRecords to topNSalariesPerDepartment(employeeRecords, n)
--> eg. {{department:"D050", salaries:{47000, 21900, missing value, missing value}}, … }
-- Derive a text report from the result.
-- Derive a text report from the result.
set report to {"Top " & n & " salaries per department:"}
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
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
end repeat
set AppleScript's text item delimiters to linefeed
return join(report, linefeed)
end task
set report to report as text
set AppleScript's text item delimiters to astid
return report
end demo


demo()</syntaxhighlight>
task()</syntaxhighlight>


{{output}}
{{output}}