我正在上课
public class Employee
{
public Employee[] ChildOrg{get; set;}
public string name {get; set;};
public string id{get; set;};
}
如何从ID中找到特定员工?
我试图使用一些跟随功能。
private static Employee GetNode(Employee objEmployeeList, string id)
{
if (objEmployeeList.ChildOrg==null)
{
return null;
}
foreach (var item in objEmployeeList.ChildOrg)
{
if (item.ID.Equals(id))
{
return (objEmployeeList)item;
}
}
foreach (var item in objEmployeeList.ChildOrg)
{
return GetNode((objEmployeeList)item, id);
}
return null;
}
正如您所看到的,我正在尝试编写一些递归函数来获取员工。
如果你仔细看它只是第一个节点的底部。
然后它返回null而不会转到任何其他节点。
请告诉我如何使用linq纠正我的功能和其他方法来完成同样的工作?
编辑: -
我想访问特定节点及其兄弟节点。
答案 0 :(得分:5)
课程中的一些变化和例程中的一些变化。
public class Employee
{
public List<Employee> ChildOrg { get; set; }
public string Name { get; set; }
public string Id { get; set; }
public Employee(string id, string name)
{
Id = id;
Name = name;
ChildOrg = new List<Employee>();
}
public Employee AddChildOrg(string id, string name)
{
var newEmployee = new Employee(id, name);
ChildOrg.Add(newEmployee);
return newEmployee;
}
public static Employee GetNode(Employee father, string id)
{
if (father != null)
{
if (father.Id.Equals(id))
return father;
if (father.ChildOrg != null)
foreach (var child in father.ChildOrg)
{
if (child.Id.Equals(id))
return child;
var employee = Employee.GetNode(child, id);
if (employee != null)
return employee;
}
}
return null;
}
}
一个小测试程序:
class Program
{
static void Main(string[] args)
{
Employee root = new Employee(1.ToString(), "root");
var e2 = root.AddChildOrg(2.ToString(), "2 second level");
var e3 = e2.AddChildOrg(3.ToString(), "3 third level");
var e1 = root.AddChildOrg(4.ToString(), "4 second level");
var e5 = e1.AddChildOrg(5.ToString(), "5 third level");
Console.WriteLine("Id 3 -> {0}", Employee.GetNode(root, "3").Name);
Console.WriteLine("Id 1 -> {0}", Employee.GetNode(root, "1").Name);
Console.WriteLine("Id 5 -> {0}", Employee.GetNode(root, "5").Name);
Console.ReadKey();
}
}
答案 1 :(得分:1)
我认为这里最好的方法是编写一个返回IEnumerable<Employee>
的递归方法,该方法迭代树中的所有节点。
给定Employee
类看起来像这样:
public class Employee
{
public Employee[] ChildOrg { get; set; }
public string name { get; set; }
public string id { get; set; }
}
您可以编写这样的递归枚举器:
public static IEnumerable<Employee> AllEmployees(Employee root)
{
if (root == null)
yield break;
yield return root;
if (root.ChildOrg == null)
yield break;
foreach (var child in root.ChildOrg.SelectMany(AllEmployees))
yield return child;
}
请注意,这将返回所有员工。如果要按ID过滤它,只需过滤枚举,例如:
var allNodesWithIdEndingIn0 = AllEmployees(root).Where(node => node.id.EndsWith("0"));
返回所有员工的枚举要灵活得多,因为您可以根据需要使用Linq处理或过滤它。
这是一个完整的可编辑控制台应用程序,演示了这种方法:
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApplication4
{
public class Employee
{
public Employee[] ChildOrg { get; set; }
public string name { get; set; }
public string id { get; set; }
}
public static class Program
{
public static IEnumerable<Employee> AllEmployees(Employee root)
{
if (root == null)
yield break;
yield return root;
if (root.ChildOrg == null)
yield break;
foreach (var child in root.ChildOrg.SelectMany(AllEmployees))
yield return child;
}
private static void Main()
{
Employee root = new Employee { name = "root", id = "root" };
createChildren(root, 4, 4, 0);
Console.WriteLine("All employees:");
Console.WriteLine(string.Join("\n", AllEmployees(root).Select(node => node.id)));
Console.WriteLine("\nAll nodes with an id that ends in 0:");
var allNodesWithIdEndingIn0 = AllEmployees(root).Where(node => node.id.EndsWith("0"));
Console.WriteLine(string.Join("\n", allNodesWithIdEndingIn0.Select(node => node.id)));
}
private static int createChildren(Employee root, int depth, int width, int count)
{
if (depth == 0)
return count;
root.ChildOrg = new Employee[width];
for (int i = 0; i < width; ++i)
{
var node = new Employee { id = count.ToString() };
root.ChildOrg[i] = node;
count = createChildren(node, depth-1, width, count+1);
}
return count;
}
}
}
访问节点的兄弟姐妹
如果您想要节点的兄弟节点,您可以返回节点的父节点ChildOrg
列表。
为此,我将编写一个名为`EmployeeAndParent的包装类,以包含节点及其父节点。
这是修改后的代码。它还演示了如何使用id ==“100”访问节点的兄弟节点:
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApplication4
{
public class Employee
{
public Employee[] ChildOrg
{
get;
set;
}
public string name
{
get;
set;
}
public string id
{
get;
set;
}
}
public class EmployeeAndParent
{
public EmployeeAndParent(Employee employee, Employee parent)
{
Employee = employee;
Parent = parent;
}
public readonly Employee Employee;
public readonly Employee Parent;
}
public static class Program
{
public static IEnumerable<EmployeeAndParent> AllEmployees(Employee root, Employee parent)
{
if (root == null)
yield break;
yield return new EmployeeAndParent(root, parent);
if (root.ChildOrg == null)
yield break;
foreach (var child in root.ChildOrg.SelectMany(child => AllEmployees(child, root)))
yield return child;
}
private static void Main()
{
Employee root = new Employee
{
name = "root",
id = "root"
};
createChildren(root, 4, 4, 0);
Console.WriteLine("All employees:");
Console.WriteLine(string.Join("\n", AllEmployees(root, null).Select(node => node.Employee.id)));
Console.WriteLine("\nAll nodes with an id that ends in 0:");
var allNodesWithIdEndingIn0 = AllEmployees(root, null).Where(node => node.Employee.id.EndsWith("0"));
Console.WriteLine(string.Join("\n", allNodesWithIdEndingIn0.Select(node => node.Employee.id)));
Console.WriteLine("\nAll siblings of the node with id == 100, along with that node itself:");
var foundNode = AllEmployees(root, null).Single(node => node.Employee.id == "100");
Console.WriteLine(string.Join("\n", foundNode.Parent.ChildOrg.Select(node => node.id)));
}
private static int createChildren(Employee root, int depth, int width, int count)
{
if (depth == 0)
return count;
root.ChildOrg = new Employee[width];
for (int i = 0; i < width; ++i)
{
var node = new Employee
{
id = count.ToString()
};
root.ChildOrg[i] = node;
count = createChildren(node, depth-1, width, count+1);
}
return count;
}
}
}
答案 2 :(得分:0)
无需使用Linq ......
private Employee GetNode(Employee employee, string id)
{
if (employee.id.Equals(id))
{
return employee;
}
if (employee.ChildOrg != null)
{
foreach (var item in employee.ChildOrg)
{
var emp = GetNode(item, id);
if (emp != null)
return emp;
}
}
return null;
}
答案 3 :(得分:0)
public class Employee
{
public Employee()
{
ChildOrg = new List<Employee>();
}
public Employee(string toString, string root)
{
ChildOrg = new List<Employee>();
Id = toString;
Name = root;
}
public IList<Employee> ChildOrg { get; set; }
public string Name { get; set; }
public string Id { get; set; }
public static Employee GetNode(Employee e, string theId)
{
if (e.Id.Equals(theId))
{
return e;
}
var employeeInList = (e.ChildOrg == null) ? null : e.ChildOrg.FirstOrDefault(item => item.Id.Equals(theId));
return employeeInList ??
e.ChildOrg.Select(item => GetNode(item, theId)).FirstOrDefault(employee => employee != null);
}
}
测试
static void Main(string[] args)
{
var root = new Employee(1.ToString(), "root");
var e1 = new Employee(2.ToString(), "1 second level");
var e2 = new Employee(3.ToString(), "2 third level");
var e3 = new Employee(4.ToString(), "3 second level");
var e4 = new Employee(5.ToString(), "4 third level");
e3.ChildOrg.Add(e4);
e2.ChildOrg.Add(e3);
e1.ChildOrg.Add(e2);
root.ChildOrg.Add(e1);
Console.WriteLine("Id 3 -> {0}", Employee.GetNode(root, "3").Name);
Console.WriteLine("Id 1 -> {0}", Employee.GetNode(root, "1").Name);
Console.WriteLine("Id 5 -> {0}", Employee.GetNode(root, "5").Name);
Console.ReadKey();
}
答案 4 :(得分:0)
定义遍历函数:
public static IEnumerable<Employee> Traverse(Employee employee)
{
yield return employee;
if (employee.ChildOrg == null) yield break;
var subordinates = employee
.ChildOrg
.SelectMany(Traverse);
foreach(var s in subordinates)
yield return s;
}
然后找到匹配元素:
var root = new Employee(...);
...
var searchId = "42";
var employee42 = Traverse(root)
.Single(e => e.id == searchId);
答案 5 :(得分:0)
试试这个
private static Employee GetNode(Employee employee, string id){
if (employee.id == id)
return employee;
if (employee.ChildOrg != null)
{
foreach (var item in employee.ChildOrg)
{
if(item.id == id)
return item;
var child = GetNode(item, id);
if(child != null)
return child;
}
}
return null;
}