现实中遇到这样一个问题:有一个项目,下边有多级任务,我们想获取项目和每一级任务的进度。很多人第一反应就是使用递归,这里先不着急探讨好不好实现。我们先来构建一个例子:
一个项目,有很多子项目(或任务),每个子项目下的子项目数和级次都是不固定的,实际的操作中,我们只需要手工录入最底层的子项目(也就是无下级子项目的项目)的进度,然后能够自动计算各个上级项目的进度,最后获取整体项目的进度。如下图所示树结构:
1、项目实体类
我们可以把这每一个项目抽出来,用一个类来表示:
一个项目包含的属性包括:项目ID、项目名称、项目权重、所属项目ID、项目进度、项目等级。
/// <summary> ??? /// 项目实体类 ??? /// </summary> ??? public class Project ??? { ??????? /// <summary> ??????? /// 获取或设置项目的ID ??????? /// </summary> ??????? /// <value>The project ID.</value> ??????? public int ProjectID { get; set; } ??????? /// <summary> ??????? /// 获取或设置项目的名称 ??????? /// </summary> ??????? /// <value>The name of the project.</value> ??????? public string ProjectName { get; set; } ??????? /// <summary> ??????? ///获取或设置项目的权重 ??????? /// </summary> ??????? /// <value>The project weights.</value> ??????? public decimal ProjectWeights { get; set; } ??????? /// <summary> ??????? /// 获取或设置项目的所属项目ID ??????? /// </summary> ??????? /// <value>The parent ID.</value> ??????? public int ParentID { get; set; } ??????? /// <summary> ??????? /// 获取或设置项目进度 ??????? /// </summary> ??????? /// <value>The project progress.</value> ??????? public decimal ProjectProgress { get; set; } ??????? /// <summary> ??????? /// 获取或设置项目的等级 ??????? /// </summary> ??????? /// <value>The project progress.</value> ??????? public decimal ProjectGrade { get; set; } ??? }
2、项目数据结构
将上边图中的数据初始化到一个List中:
?projectList = new List<Project>(); ??????????? projectList.Add(new Project(1, "我的项目", 1, 0, 0, 1)); ??????????? projectList.Add(new Project(2, "子项目1", new decimal(0.50), 1, 0, 2)); ??????????? projectList.Add(new Project(3, "子项目2", new decimal(0.50), 1, 0, 2)); ??????????? projectList.Add(new Project(4, "子项目11", new decimal(0.40), 2, 0, 3)); ??????????? projectList.Add(new Project(5, "子项目12", new decimal(0.60), 2, 0, 3)); ??????????? projectList.Add(new Project(6, "子项目121", new decimal(0.50), 5, 0, 4)); ??????????? projectList.Add(new Project(7, "子项目122", new decimal(0.50), 5, 0, 4)); ??????????? projectList.Add(new Project(8, "子项目1221", new decimal(0.20), 7, 0, 5)); ??????????? projectList.Add(new Project(9, "子项目1222", new decimal(0.80), 7, 0, 5)); ??????????? projectList.Add(new Project(10, "子项目21", new decimal(0.20), 3, 0, 3)); ??????????? projectList.Add(new Project(11, "子项目22", new decimal(0.40), 3, 0, 3)); ??????????? projectList.Add(new Project(12, "子项目23", new decimal(0.20), 3, 0, 3)); ??????????? projectList.Add(new Project(13, "子项目231", new decimal(0.50), 12, 0, 4)); ??????????? projectList.Add(new Project(14, "子项目232", new decimal(0.50), 12, 0, 4));
3、设置无下级项目的进度值
检查是否有下级子项目:
private bool IsProjectHasSubProject(int projectID) ??????? { ??????????? foreach (Project objProject in parojectList) ??????????? { ??????????????? if (objProject.ParentID == projectID) ??????????????? { ??????????????????? return true; ??????????????? } ??????????? } ??????????? return false; ??????? }
遍历每个项目,如果没有下级项目,则设置一个百分值。
Random ro = new Random(); ??????????? foreach (Project objProject in projectList) ??????????? { ??????????????? if (!IsProjectHasSubProject(objProject.ProjectID)) ??????????????? { ??????????????????? objProject.ProjectProgress = new decimal(ro.Next(0, 100)); ??????????????? } ??????????? }
递归添加到Treeview,显示出来看看:
private void ShowTreeView() ??????? { ??????????? treeView1.Nodes.Clear(); ??????????? InitTreeView(treeView1.Nodes, 0); ??????????? treeView1.ExpandAll(); ??????? } private void InitTreeView(TreeNodeCollection collection, int parentID) ??????? { ??????????? foreach (Project objProject in projectList) ??????????? { ??????????????? if (objProject.ParentID == parentID) ??????????????? { ??????????????????? TreeNode node = new TreeNode(objProject.ProjectName + " [权重:" + objProject.ProjectWeights + " 进度:" + objProject.ProjectProgress + "%]"); ??????????????????? collection.Add(node); ??????????????????? InitTreeView(node.Nodes, objProject.ProjectID); ??????????????? } ??????????? } ??????? }
4、计算项目进度
很多人想到的都是递归,这里先用递归试试:
private void FormTopToBottomRecursiveProgressCal(Project parentProject) ??????? { ??????????? decimal progressCount = 0; ??????????? foreach (Project objProject in projectList) ??????????? { ??????????????? if (objProject.ParentID == parentProject.ProjectID) ??????????????? { ??????????????????? if (objProject.ProjectProgress == 0) ??????????????????? { ??????????????????????? FormTopToBottomRecursiveProgressCal(objProject); ??????????????????? } ??????????????????? progressCount += objProject.ProjectProgress * objProject.ProjectWeights; ??????????????? } ??????????? } ??????????? progressCount = decimal.Round(progressCount, 2); ??????????? parentProject.ProjectProgress = progressCount; ??????? }
?看起来不错,代码挺简洁。
这里再提供一种方法:按照级次计算,从最低的级次开始计算:
首先实现一个类,用来项目级次排序:
/// <summary> ??? /// 排序项目级次 ??? /// </summary> ??? public class SortProjectGrade : IComparer<Project> ??? { ??????? /// <summary> ??????? /// Compares the specified project1. ??????? /// </summary> ??????? /// <param name="project1">The project1.</param> ??????? /// <param name="project2">The project2.</param> ??????? /// <returns></returns> ??????? public int Compare(Project project1, Project project2) ??????? { ??????????? if (project1 != null && project2 != null) ??????????? { ??????????????? if (project1.ProjectGrade == project2.ProjectGrade) ??????????????????? return 0; ??????????????? else ??????????????????? return project1.ProjectGrade > project2.ProjectGrade ? 1 : -1; ??????????? } ??????????? return -1; ??????? } ??? }
下边是用来计算进度的方法:
private void FromBottomToTopGradeCalProgress() ??????? { ??????????? //获取项目级次 ??????????? SortProjectGrade objSortProjectGrade = new SortProjectGrade(); ??????????? projectList.Sort(objSortProjectGrade); ??????????? int grade = projectList[projectList.Count - 1].ProjectGrade; ??????????? //遍历每个级次 ??????????? for (int i = grade - 1; i > 0; i--) ??????????? { ??????????????? //遍历项目列表,获取当前级次 ??????????????? foreach (Project project in projectList) ??????????????? { ??????????????????? if (project.ProjectGrade == i) ??????????????????? { ??????????????????????? //获取项目的下级,求和 ??????????????????????? int count = 0; ??????????????????????? decimal progressCount = 0; ??????????????????????? foreach (Project subproject in projectList) ??????????????????????? { ??????????????????????????? if (subproject.ParentID == project.ProjectID) ??????????????????????????? { ??????????????????????????????? progressCount += subproject.ProjectProgress * subproject.ProjectWeights; ??????????????????????????????? count++; ??????????????????????????? } ??????????????????????? } ??????????????????????? if (count != 0) ??????????????????????? { ??????????????????????????? progressCount = decimal.Round(progressCount, 2); ??????????????????????????? project.ProjectProgress = progressCount; ??????????????????????? } ??????????????????? } ??????????????? } ??????????? } ??????? }
使用两种方法都可以准确的计算进度,如图计算结果:
使用递归或者根据级次循环计算,可能有时候选择会不一样。
本文仅提供参考,欢迎就此问题与我交流。
发表评论
相关文章
国内AI资源汇总,AI聊天、AI绘画、AI写作、AI视频、AI设计、AI编程、AI音乐等,国内顺畅访问,无需科学上网。
扫码或点击进入:萤火AI大全
文章分类
最新评论