如何在Go编程语言中从分层数据中找到控制范围(span of control)

huangapple go评论95阅读模式
英文:

How to find span of control from a hierarchical data in Go programming language

问题

控制范围是指直接和间接报告给经理的人数(即包括报告给下属的人数,直到没有人报告给该成员为止),以了解组织结构中团队的完整规模。

我在下面提供了一个实现。它给出了正确的结果,但我不确定这是否真的是最好的方法。我是一个新手。请问有人可以推荐一种更好的方法来在Go语言中实现这个吗?如果可能的话,可能是一种更优雅的方法。提前谢谢!

package main

import "fmt"

func main() {

	orgData := []EmpRecord{
		{"E123", "Annapurna", "E456", "Ananya"},
		{"E789", "Arya", "E234", "Manisha"},
		{"E345", "Madhura", "E456", "Ananya"},
		{"E456", "Ananya", "E234", "Manisha"},
		{"E567", "Bharat", "E123", "Annapurna"},
		{"E678", "Shart", "E789", "Arya"},
		{"E101", "Akash", "E123", "Annapurna"},
		{"E102", "Anil", "E789", "Arya"},
		{"E103", "Vikas", "E123", "Annapurna"},
		{"E104", "Vivek", "E123", "Annapurna"},
		{"E105", "Ankita", "E456", "Ananya"},
		{"E106", "Atul", "E123", "Annapurna"},
		{"E107", "Priya", "E789", "Arya"},
		{"E234", "Manisha", "E999", "Albert"},
	}

	socList := make(map[string]int)
	var ix int = 0

	soc(orgData, socList, &ix)

	fmt.Println(socList)

}

type EmpRecord struct {
	EmpId   string
	EmpName string
	SupId   string
	SupName string
}

func soc(m []EmpRecord, socList map[string]int, rc *int) {
	for _, v := range m {
		_, ok := socList[v.SupId]
		if !ok {
			loopRecurive(v.SupId, m, rc)
			if *rc > 0 {
				socList[v.SupId] = *rc
				*rc = 0
			}
		}
	}

}

func loopRecurive(v string, er []EmpRecord, rc *int) {
	for _, x := range er {
		if v == x.SupId {
			*rc++
			loopRecurive(x.EmpId, er, rc)
		}
	}
}

最终输出打印为 map[E123:5 E234:13 E456:8 E789:3 E999:14]

英文:

Span of control refers to the number of people reporting to a manager both directly and indirectly(i.e., including the number of people reporting to the people reporting to him/her up until down below where the member has no one reporting to him/her) to know the full size of the team in his/her org structure.

I've put an implementation below. It gives the correct result But, I'm not sure if this is the best way really. I'm a novice. Can some one please recommend a better way to achieve this in Go language? Probably a more elegant approach, if possible. Thanks in advance!

package main

import "fmt"

func main() {

	orgData := []EmpRecord{
		{"E123", "Annapurna", "E456", "Ananya"},
		{"E789", "Arya", "E234", "Manisha"},
		{"E345", "Madhura", "E456", "Ananya"},
		{"E456", "Ananya", "E234", "Manisha"},
		{"E567", "Bharat", "E123", "Annapurna"},
		{"E678", "Shart", "E789", "Arya"},
		{"E101", "Akash", "E123", "Annapurna"},
		{"E102", "Anil", "E789", "Arya"},
		{"E103", "Vikas", "E123", "Annapurna"},
		{"E104", "Vivek", "E123", "Annapurna"},
		{"E105", "Ankita", "E456", "Ananya"},
		{"E106", "Atul", "E123", "Annapurna"},
		{"E107", "Priya", "E789", "Arya"},
		{"E234", "Manisha", "E999", "Albert"},
	}

	socList := make(map[string]int)
	var ix int = 0

	soc(orgData, socList, &ix)

	fmt.Println(socList)

}

type EmpRecord struct {
	EmpId   string
	EmpName string
	SupId   string
	SupName string
}

func soc(m []EmpRecord, socList map[string]int, rc *int) {
	for _, v := range m {
		_, ok := socList[v.SupId]
		if !ok {
			loopRecurive(v.SupId, m, rc)
			if *rc > 0 {
				socList[v.SupId] = *rc
				*rc = 0
			}
		}
	}

}

func loopRecurive(v string, er []EmpRecord, rc *int) {
	for _, x := range er {
		if v == x.SupId {
			*rc++
			loopRecurive(x.EmpId, er, rc)
		}
	}
}

The final output prints map[E123:5 E234:13 E456:8 E789:3 E999:14]

答案1

得分: 1

这更像是一个算法问题,而不是特定于某种语言。层次数据遵循树形结构。

如果你看到的关系是员工有一个领导领导可以有多个直接下属,如果我们构建一个类似树的结构,这将更容易。

树节点结构

type EmpRecord struct {
	EmpId   string
	EmpName string
	reportees     *EmpRecord[]
}

请注意,您需要先创建rootNode,它将是CEO或部门负责人。

现在,为了找到所有的直接下属,您可以使用广度优先的方法按层级查找员工,或者使用深度优先的方法找到所有的直接和间接下属,没有特定的顺序。

注意:您需要知道与特定员工对应的节点的地址。您可以使用哈希映射,例如[empName] => [指向employeeRecord的指针]或任何适用的键。

注意:如果您想要反向搜索,从员工到所有上级经理,您可以创建双向树结构。在节点中还将保存指向上级的指针。

英文:

This is more of an algorithmic problem than language-specific. The hierarchical data follows a tree structure.

If you see the relationship's here will be something like Employee has one leader and leader can have more than one direct-reportees. If we build a tree-like structure this will be easier.

Tree Node Structure

type EmpRecord struct {
EmpId   string
EmpName string
reportees     *EmpRecord[]
}

Note that you will have to create the rootNode first that will be the CEO or head of the department.

Now in order to find all the direct reportees you can use Breadth-First approach to find employees by level or depth-first-approach to find all the direct-indirect reporters with no specific ordering.

Note: You will need to know the address of the node corresponding to a particular employee. You can use a hashmap s.t [empName] => [pointer to employeeRecord] or whichever key works.

Note:- If you want to search the other way. From employees to all his manager's you can create two-way tree structure. Where you will also keep pointer to the superior with the node.

答案2

得分: 0

有人能否推荐一种更好的方法...

"更好的方法"可以有很多含义,包括:

  • 更快
  • 更低的内存使用
  • 更易于理解/维护

因此,你的问题是主观的;我们可以向你展示其他的方法,但不能真正说它们是"更好"的。下面是我认为更容易理解的一种替代方法(playground)。

package main

import "fmt"

type EmpRecord struct {
	EmpId   string
	EmpName string
	SupId   string
	SupName string
}

type EmpWithReports struct {
	EmpRecord
	Reports []*EmpWithReports
}

func main() {

	orgData := []EmpRecord{
		{"E123", "Annapurna", "E456", "Ananya"},
		{"E789", "Arya", "E234", "Manisha"},
		{"E345", "Madhura", "E456", "Ananya"},
		{"E456", "Ananya", "E234", "Manisha"},
		{"E567", "Bharat", "E123", "Annapurna"},
		{"E678", "Shart", "E789", "Arya"},
		{"E101", "Akash", "E123", "Annapurna"},
		{"E102", "Anil", "E789", "Arya"},
		{"E103", "Vikas", "E123", "Annapurna"},
		{"E104", "Vivek", "E123", "Annapurna"},
		{"E105", "Ankita", "E456", "Ananya"},
		{"E106", "Atul", "E123", "Annapurna"},
		{"E107", "Priya", "E789", "Arya"},
		{"E234", "Manisha", "E999", "Albert"},
	}

	empMap := make(map[string]*EmpWithReports)
	for _, emp := range orgData {
		empMap[emp.EmpId] = &EmpWithReports{EmpRecord: emp}
	}
	// 为每个员工添加报告
	for _, e := range empMap {
		if boss := empMap[e.SupId]; boss != nil {
			boss.Reports = append(boss.Reports, e)
		} else if e.SupId != "E999" {
			panic(fmt.Sprintf("Employee %s: Boss %s not found", e.EmpId, e.SupId))
		}
	}

	// 获取计数
	socList := make(map[string]int)
	for _, e := range empMap {
		s := soc(empMap, e)
		if s > 0 {
			socList[e.EmpId] = s
		}
	}
	fmt.Println(socList)

}

func soc(empMap map[string]*EmpWithReports, emp *EmpWithReports) int {
	var s int
	for _, rep := range emp.Reports {
		s += 1 + soc(empMap, rep)
	}
	return s
}

结果是 map[E123:5 E234:13 E456:8 E789:3]E999 没有包含在内,如果需要的话,可以很容易添加)。

英文:

> Can some one please recommend a better way...

"better way" can mean many things including:

  • Quicker
  • Lower memory use
  • Easier to understand/maintain

As such your question is subjective; we can show you other ways of doing this but cannot really say that they are "better". Below is one alternative approach that I feel is easier to understand (playground).

package main
import "fmt"
type EmpRecord struct {
EmpId   string
EmpName string
SupId   string
SupName string
}
type EmpWithReports struct {
EmpRecord
Reports []*EmpWithReports
}
func main() {
orgData := []EmpRecord{
{"E123", "Annapurna", "E456", "Ananya"},
{"E789", "Arya", "E234", "Manisha"},
{"E345", "Madhura", "E456", "Ananya"},
{"E456", "Ananya", "E234", "Manisha"},
{"E567", "Bharat", "E123", "Annapurna"},
{"E678", "Shart", "E789", "Arya"},
{"E101", "Akash", "E123", "Annapurna"},
{"E102", "Anil", "E789", "Arya"},
{"E103", "Vikas", "E123", "Annapurna"},
{"E104", "Vivek", "E123", "Annapurna"},
{"E105", "Ankita", "E456", "Ananya"},
{"E106", "Atul", "E123", "Annapurna"},
{"E107", "Priya", "E789", "Arya"},
{"E234", "Manisha", "E999", "Albert"},
}
empMap := make(map[string]*EmpWithReports)
for _, emp := range orgData {
empMap[emp.EmpId] = &EmpWithReports{EmpRecord: emp}
}
// Add reports for each employee
for _, e := range empMap {
if boss := empMap[e.SupId]; boss != nil {
boss.Reports = append(boss.Reports, e)
} else if e.SupId != "E999" {
panic(fmt.Sprintf("Employee %s: Boss %s not found", e.EmpId, e.SupId))
}
}
// Get the counts
socList := make(map[string]int)
for _, e := range empMap {
s := soc(empMap, e)
if s > 0 {
socList[e.EmpId] = s
}
}
fmt.Println(socList)
}
func soc(empMap map[string]*EmpWithReports, emp *EmpWithReports) int {
var s int
for _, rep := range emp.Reports {
s += 1 + soc(empMap, rep)
}
return s
}

The results are map[E123:5 E234:13 E456:8 E789:3] (E999 is not included because they are not in the list; this would be simple to add if required).

huangapple
  • 本文由 发表于 2021年7月29日 13:07:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/68570350.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定