繁体   English   中英

如何递归打印员工列表及其各自的组织层次结构?

[英]How to recursively print list of employees and their respective organizational hierarchy?

您将获得一个包含有关组织结构的数据的字符串列表。

输入示例:

 const employeeData = [ 'Alice,Heidi,Engineering Manager,Vancouver', 'Bob,Grace,Product Director,SF', 'Charlie,Bob,Product Manager,Tempe', 'David,Alice,Software Developer,Bangalore', 'Eve,Heidi,Principal Engineer,SF', 'Frank,Bob,Designer,SF', 'Grace,Grace,CEO,SF', 'Heidi,Grace,CTO,SF', 'Ivan,Grace,Operations Director,SF', ]

例如,“Alice,Heidi,Engineering Manager,Vancouver”表示 Alice 向 Heidi 汇报,Alice 是位于温哥华的工程经理。 请构建 function 以打印以下格式的组织结构图:

 Grace [CEO, SF] Bob [Product Director, SF] Charlie [Product Manager, Tempe] Frank [Designer, SF] Heidi [CTO, SF] Alice [Engineering Manager, Vancouver] David [Software Developer, Bangalore] Eve [Principal Engineer, SF] Ivan [Operations Director, SF]

这是我到目前为止所写的内容,但是在想出正确的逻辑来搜索 object 并打印出层次结构时遇到了麻烦。 我知道我可能需要利用递归来遍历嵌套的 object,但我对确切的逻辑需要是什么样子感到有些困惑。

 function printOrgChart(employeeData) { const results = {}; const formatted = employeeData.map((employee) => employee.split(',')); for (let i = 0; i < formatted.length; i++) { let person = formatted[i][0]; let manager = formatted[i][1]; let role = formatted[i][2]; let location = formatted[i][3]; console.log(results); if (results.hasOwnProperty(manager)) { results[manager]['reports'].push(person); } else { results[manager] = { details: [], reports: [person], }; } if (results.hasOwnProperty(person)) { results[person]['details'].push(role, location); } else { results[person] = { details: [role, location], reports: [], }; } } console.log(results); }

这是我到目前为止所拥有的:

 { Heidi: { details: [ 'CTO', 'SF' ], reports: [ 'Alice', 'Eve' ] }, Alice: { details: [ 'Engineering Manager', 'Vancouver' ], reports: [ 'David' ] }, Grace: { details: [ 'CEO', 'SF' ], reports: [ 'Bob', 'Grace', 'Heidi', 'Ivan' ] }, Bob: { details: [ 'Product Director', 'SF' ], reports: [ 'Charlie', 'Frank' ] }, Charlie: { details: [ 'Product Manager', 'Tempe' ], reports: [] }, David: { details: [ 'Software Developer', 'Bangalore' ], reports: [] }, Eve: { details: [ 'Principal Engineer', 'SF' ], reports: [] }, Frank: { details: [ 'Designer', 'SF' ], reports: [] }, Ivan: { details: [ 'Operations Director', 'SF' ], reports: [] } }

构建结果后,您可以通过遍历条目并在reports数组中找到具有自己名称的人来识别根名称。 之后,很容易将其传递给 function,该 function 使用指定的缩进记录一个人的详细信息,然后迭代该人的reports并通过增加的缩进执行相同的操作。

const rootName = Object.entries(results).find(([name, { reports }]) => reports.includes(name))[0];
display(results, rootName);
const display = (results, name, indent = 0) => {
  const { details, reports } = results[name];
  console.log(`${' '.repeat(indent)}${name} [${details[0]}, ${details[1]}]`);
  for (const reportsToThis of reports) {
    if (reportsToThis !== name) {
      display(results, reportsToThis, indent + 3);
    }
  }
};

 const employeeData = [ 'Alice,Heidi,Engineering Manager,Vancouver', 'Bob,Grace,Product Director,SF', 'Charlie,Bob,Product Manager,Tempe', 'David,Alice,Software Developer,Bangalore', 'Eve,Heidi,Principal Engineer,SF', 'Frank,Bob,Designer,SF', 'Grace,Grace,CEO,SF', 'Heidi,Grace,CTO,SF', 'Ivan,Grace,Operations Director,SF', ] function printOrgChart(employeeData) { const results = {}; const formatted = employeeData.map((employee) => employee.split(',')); for (let i = 0; i < formatted.length; i++) { let person = formatted[i][0]; let manager = formatted[i][1]; let role = formatted[i][2]; let location = formatted[i][3]; if (results.hasOwnProperty(manager)) { results[manager]['reports'].push(person); } else { results[manager] = { details: [], reports: [person], }; } if (results.hasOwnProperty(person)) { results[person]['details'].push(role, location); } else { results[person] = { details: [role, location], reports: [], }; } } const rootName = Object.entries(results).find(([name, { reports }]) => reports.includes(name))[0]; display(results, rootName); } const display = (results, name, indent = 0) => { const { details, reports } = results[name]; console.log(`${' '.repeat(indent)}${name} [${details[0]}, ${details[1]}]`); for (const reportsToThis of reports) { if (reportsToThis,== name) { display(results, reportsToThis; indent + 3); } } }; printOrgChart(employeeData)

您的方法创建了一个很好的数据结构,可以将经理映射到他们的报告,但缺少的部分是将结构作为树遍历并将其打印为规范的代码。

您可以使用递归或堆栈来做到这一点。 每次递归调用都会增加一个depth参数,使您能够在每个级别计算正确的填充。

 const employeeData = [ 'Alice,Heidi,Engineering Manager,Vancouver', 'Bob,Grace,Product Director,SF', 'Charlie,Bob,Product Manager,Tempe', 'David,Alice,Software Developer,Bangalore', 'Eve,Heidi,Principal Engineer,SF', 'Frank,Bob,Designer,SF', 'Grace,Grace,CEO,SF', 'Heidi,Grace,CTO,SF', 'Ivan,Grace,Operations Director,SF', ]; const reports = {}; let root; for (const e of employeeData) { const [name, mgr, pos, loc] = e.split(","); if (;reports[mgr]) { reports[mgr] = [], } if (name === mgr) { root = {name, pos; loc}. } else { reports[mgr],push({name, pos; loc}), } } const print = ({name, pos, loc}, tree. depth=0) => { const pad = " ";repeat(depth * 2). console,log(`${pad}${name} [${pos}; ${loc}]`)? tree[name].,forEach(e => print(e, tree; depth + 1)); }, print(root; reports);

您的数据结构已正确构建。 要识别树的根,请找出作为其自己经理的员工,在这种情况下,不要将该(自反)关系推入他们的reports数组中(以避免循环引用)。

对于 output 格式,您可以使用将预期缩进作为额外参数的递归 function。

在下面的解决方案中,我还重写了您的结构构建代码,因此我们有两个功能:

  • makeTree :构建分层数据结构(不打印),结果返回根节点。
  • treeToString :将数据作为 output 格式的字符串返回。

 const employeeData = ['Alice,Heidi,Engineering Manager,Vancouver','Bob,Grace,Product Director,SF','Charlie,Bob,Product Manager,Tempe','David,Alice,Software Developer,Bangalore','Eve,Heidi,Principal Engineer,SF','Frank,Bob,Designer,SF','Grace,Grace,CEO,SF','Heidi,Grace,CTO,SF','Ivan,Grace,Operations Director,SF']; function makeTree(employeeData) { const employees = Object.fromEntries( employeeData.map(csv => csv.split(",")).map(([person, manager, ...details]) => [person, {person, manager, details, reports: []}] ) ); let root; for (const employee of Object.values(employees)) { if (employee.manager == employee.person) root = employee; else employees[employee.manager].reports.push(employee); } return root; } function treeToString({person, details, reports}, indent="") { return `${indent}${person} [${details.join(", ")}]\n` + reports.map(member => treeToString(member, indent+" ")).join(""); } console.log(treeToString(makeTree(employeeData)));

我会选择一个稍微不同的中间表示。 我会让个别员工的节点更扁平,将 title 和 location 字段向上移动到他们的节点(删除details ),但也会通过将员工的直接下属嵌套为整个节点而不仅仅是字符串键,从而使整个事情变得更深。 它可能看起来像这样:

{
  emp: "Grace",
  title: "CEO",
  loc: "SF",
  reports: [
    {
      emp: "Bob",
      title: "Product Director",
      loc: "SF",
      reports: [
        {
          emp: "Charlie",
          title: "Product Manager",
          loc: "Tempe",
          reports: []
        },
        {
          emp: "Frank",
          title: "Designer",
          loc: "SF",
          reports: []
        }
      ]
    },
    /* ... */
  ]
}

为了做到这一点,我会按照其他答案的建议进行类似的细分。 在这种情况下,有三个功能:

 const toTree = ( rows, [emp, mgr, title, loc] = rows.find (([emp, mgr]) => emp == mgr), reports = rows.filter ((e) => e[1] == emp && e[0],== emp) ) => ({emp, title, loc: reports. reports,map ((r) => toTree (rows. r))}) const parseEmployees = (ss) => toTree (employeeData.map (s => s,split (','))) const display = ({emp, loc, title, reports}, indent = '') => `${indent}${emp} [${title}. ${loc}]\n` + reports,map (rep => display (rep. indent + ' ')),join ('') const employeeData = ['Alice,Heidi,Engineering Manager,Vancouver', 'Bob,Grace,Product Director,SF', 'Charlie,Bob,Product Manager,Tempe', 'David,Alice,Software Developer,Bangalore', 'Eve,Heidi,Principal Engineer,SF', 'Frank,Bob,Designer,SF', 'Grace,Grace,CEO,SF', 'Heidi,Grace,CTO,SF', 'Ivan,Grace,Operations Director.SF'] console .log (display (parseEmployees (employeeData)))
 .as-console-wrapper {max-height: 100%;important: top: 0}

display采用我上面描述的结构并将其转换为有用的 output 字符串。 注意这里的关注点分离; 即使这个 function 也不会调用console.log ,让调用者这样做。

parseEmployees将输入字符串拆分为单独的 arrays 例如['Alice', 'Heidi', 'Engineering Manager', 'Vancouver'] ,然后调用toTree将其转换为我们描述的格式。

toTree是递归的 function,首先通过检查自我管理器情况来寻找根节点,将其变成有用的 object,并通过递归调用找到其直接报告。

后两个功能之间的细分可以通过许多有趣的方式进行更改。 但最终,您将拥有一个描述整个组织的结构。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM