您將獲得一個包含有關組織結構的資料的字串串列。
輸入示例:
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 是位于溫哥華的工程經理。請構建一個函式來列印以下格式的組織結構圖:
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]
這是我到目前為止所寫的,但是在想出正確的邏輯來搜索物件并列印出層次結構時遇到了麻煩。我知道我可能需要利用遞回來遍歷嵌套物件,但我對確切的邏輯需要是什么樣子感到有些困惑。
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: [] } }
uj5u.com熱心網友回復:
構建結果后,您可以通過遍歷條目并找到在其reports
陣列中具有自己名稱的人來識別根名稱。之后,很容易將其傳遞給一個函式,該函式使用指定的縮進記錄一個人的詳細資訊,然后迭代該人的資訊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)
uj5u.com熱心網友回復:
您的方法創建了一個很好的資料結構,可以將經理映射到他們的報告,但缺少的部分是將結構作為樹遍歷并將其列印為規范的代碼。
您可以使用遞回或堆疊來做到這一點。每次遞回呼叫都會增加一個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);
uj5u.com熱心網友回復:
您的資料結構已正確構建。要識別樹的根,請找出作為其自己經理的員工,在這種情況下,不要將該(自反)關系推入他們的reports
陣列中(以避免回圈參考)。
對于輸出格式,您可以使用將預期縮進作為額外引數的遞回函式。
在下面的解決方案中,我還重寫了您的結構構建代碼,因此我們有兩個功能:
makeTree
:構建分層資料結構(不列印),結果回傳根節點。treeToString
:將資料作為輸出格式的字串回傳。
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)));
uj5u.com熱心網友回復:
我會選擇一個稍微不同的中間表示。我會讓單個員工的節點更扁平,將 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
采用我上面描述的結構并將其轉換為有用的輸出字串。注意這里的關注點分離;即使這個函式不呼叫console.log
,讓它的呼叫者這樣做。
parseEmployees
將輸入字串拆分為單獨的陣列,例如['Alice', 'Heidi', 'Engineering Manager', 'Vancouver']
,然后呼叫toTree
將其轉換為我們描述的格式。
toTree
是遞回函式,首先通過檢查自我管理器的情況來尋找根節點,將其變成有用的物件,然后通過遞回呼叫找到它的直接下屬。
后兩個功能之間的細分可以通過許多有趣的方式進行更改。但最終,您將擁有一個描述整個組織的結構。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/507826.html
標籤:javascript 算法 递归
上一篇:Java遞回索引超出范圍1
下一篇:二進制字串播放