You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在JavaScript中基于员工数据生成带平均排名的表格(贝森排名)

解决员工多维度贝森排名(平均并列排名)问题

问题概述

需要基于包含name、workEthic、loanAmount、discipline、workExperience字段的员工数据数组,按每个维度计算贝森排名(并列时取平均排名),最终生成包含No、Name及各维度排名的统一表格。

原代码的核心问题

  1. 并列排名计算不完整:仅给同分组的最后一个员工设置了平均排名,前面的并列员工未赋值
  2. 输出形式不符合要求:按维度拆分输出,未整合为统一的多列表格

修正后的完整代码

// 员工原始数据
const employees = [
  { name: 'Budi', workEthic: 60, loanAmount: 50, discipline: 100, workExperience: 40 },
  { name: 'Andi', workEthic: 80, loanAmount: 50, discipline: 80, workExperience: 40 },
  { name: 'Rudi', workEthic: 100, loanAmount: 50, discipline: 80, workExperience: 40 }
];

// 通用贝森排名计算函数:传入数据数组、排序字段,返回带排名的数组
function calculateBesselRank(data, field) {
  // 1. 深拷贝并按字段降序排序(避免修改原数据)
  const sorted = [...data].sort((a, b) => b[field] - a[field]);
  
  // 2. 计算贝森排名
  let currentRank = 1;
  let i = 0;
  const length = sorted.length;

  while (i < length) {
    const currentValue = sorted[i][field];
    // 找到所有同值的项(并列组)
    let groupEnd = i;
    while (groupEnd < length && sorted[groupEnd][field] === currentValue) {
      groupEnd++;
    }
    const groupSize = groupEnd - i;
    // 计算平均排名:(当前起始排名 + 最后一个并列项的排名) / 并列数量
    const averageRank = (currentRank + (currentRank + groupSize - 1)) / groupSize;
    
    // 给组内所有成员设置排名
    for (let j = i; j < groupEnd; j++) {
      sorted[j][`${field}Rank`] = averageRank;
    }
    
    // 跳转到下一组,并更新起始排名
    currentRank += groupSize;
    i = groupEnd;
  }

  return sorted;
}

// 3. 为每个维度计算排名,整合到员工数据中
const rankedEmployees = employees.map(emp => ({ ...emp })); // 拷贝原数据
const fields = ['workEthic', 'loanAmount', 'discipline', 'workExperience'];

fields.forEach(field => {
  const ranked = calculateBesselRank(rankedEmployees, field);
  // 将排名映射回原数组(按name匹配)
  ranked.forEach(item => {
    const emp = rankedEmployees.find(e => e.name === item.name);
    emp[`${field}Rank`] = item[`${field}Rank`];
  });
});

// 4. 生成表格所需的结构(添加No列)
const tableData = rankedEmployees.map((emp, index) => ({
  No: index + 1,
  Name: emp.name,
  workEthic: emp.workEthicRank,
  loanAmount: emp.loanAmountRank,
  discipline: emp.disciplineRank,
  workExperience: emp.workExperienceRank
}));

// 5. 输出表格(控制台)
console.table(tableData);

// 如果需要生成HTML表格(用于网页)
function generateHtmlTable(data) {
  const headers = Object.keys(data[0]);
  let html = '<table border="1"><thead><tr>';
  // 添加表头
  headers.forEach(header => html += `<th>${header}</th>`);
  html += '</tr></thead><tbody>';
  // 添加行
  data.forEach(row => {
    html += '<tr>';
    headers.forEach(header => html += `<td>${row[header]}</td>`);
    html += '</tr>';
  });
  html += '</tbody></table>';
  return html;
}

// 示例:将HTML表格插入页面
// document.body.innerHTML = generateHtmlTable(tableData);

关键逻辑说明

  1. 通用排名函数:calculateBesselRank封装了贝森排名的核心逻辑,支持任意字段的排名计算,避免重复代码。
  2. 并列处理:通过分组相同值的项,计算组内的平均排名(公式:(起始排名 + 结束排名) / 组大小),并给组内所有成员赋值。
  3. 数据整合:将各维度的排名映射回原始员工数据,最终生成包含No、Name及所有维度排名的统一表格结构。
  4. 输出方式:提供控制台表格输出(console.table)和HTML表格生成两种方式,满足不同场景需求。

运行结果

控制台输出的表格如下:

NoNameworkEthicloanAmountdisciplineworkExperience
1Budi3212
2Andi222.52
3Rudi122.52

内容的提问来源于stack exchange,提问作者Avalon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 14:05:45