Net 6.0层级数据转换:嵌套If转LINQ与Lambda优化
层级数据格式化问题及解决方案
需求背景
基于Net 6.0环境,需要将特定格式的层级记录转换为度量布局格式。
原始输入格式
AAA|0000A|000AA|0001A AAA|0000A|000AA|0002A AAA|0000A|000AB|0001B AAA|0000A|000AB|0002B AAA|0000B|000BA|0001A AAA|0000B|000BB|0001B
期望输出格式
AAA|BLANK|BLANK|BLANK AAA|0000A|BLANK|BLANK AAA|0000B|BLANK|BLANK AAA|0000A|000AA|BLANK AAA|0000A|000AB|BLANK AAA|0000B|000BA|BLANK AAA|0000B|000BB|BLANK AAA|0000A|000AA|0001A AAA|0000A|000AA|0002A AAA|0000A|000AA|0003A AAA|0000A|000AA|0004A AAA|0000A|000AB|0001B AAA|0000A|000AB|0002B AAA|0000B|000BA|0001A AAA|0000B|000BB|0001B
自定义对象定义
定义HierarchyStructure类用于承载层级数据:
public class HierarchyStructure { public string Employer { get; set; } public string Level1 { get; set; } public string Level2 { get; set; } public string Level3 { get; set; } public string Level4 { get; set; } public bool isRxlvl3 { get; set; } public bool isExpired { get; set; } public string lvl4SubType { get; set; } public HierarchyStructure(string employer, string? level1 = null, string? level2 = null, string? level3 = null, string? level4 = null, bool isRxlvl3 = false, bool isExpired = false, string? lvl4SubType = null) { this.Employer = employer; this.Level1 = string.IsNullOrEmpty(level1) ? string.Empty : level1; this.Level2 = string.IsNullOrEmpty(level2) ? string.Empty : level2; this.Level3 = string.IsNullOrEmpty(level3) ? string.Empty : level3; this.Level4 = string.IsNullOrEmpty(level4) ? string.Empty : level4; this.isRxlvl3 = isRxlvl3; this.isExpired = isExpired; this.lvl4SubType = string.IsNullOrEmpty(lvl4SubType) ? string.Empty : lvl4SubType; } }
初始实现问题
通过两个只读属性获取层级数据列表:
private List<HierarchyStructure> AllLevels => _allLevels; private List<HierarchyStructure> LocationLevels => _LocationLevels;
最初为每个层级单独编写去重数据获取方法,但方法逻辑重复,无法合并为递归或动态方法:
public bool GetDistinctEmployers() { var selectedLevels = (from levels in AllLevels select new HierarchyStructure(levels.Employer)); foreach(HierarchyStructure level in selectedLevels) LocationLevels.Add(level); return true; } public bool GetDistinctLevel1(string emp) { var selectedLevels = (from levels in AllLevels where levels.Employer == emp select new HierarchyStructure(levels.Employer,levels.Level1)); foreach(HierarchyStructure level in selectedLevels) LocationLevels.Add(level); return true; } public bool GetDistinctLevel2(string lvl) { var selectedLevels = (from levels in AllLevels where levels.Level1 == lvl select new HierarchyStructure(levels.Employer,levels.Level1, levels.Level2)); foreach(HierarchyStructure level in selectedLevels) LocationLevels.Add(level); return true; } public bool GetDistinctLevel3(string lvl) { var selectedLevels = (from levels in AllLevels where levels.Level2 == lvl select new HierarchyStructure(levels.Employer,levels.Level1, levels.Level2, levels.Level3)); foreach(HierarchyStructure level in selectedLevels) LocationLevels.Add(level); return true; } public bool GetDistinctLevel4(string lvl) { var selectedLevels = (from levels in AllLevels where levels.Level3 == lvl select new HierarchyStructure(levels.Employer,levels.Level1, levels.Level2, levels.Level3, levels.Level4)); foreach(HierarchyStructure level in selectedLevels) LocationLevels.Add(level); return true; }
尝试合并方法时,代码嵌套过深,触发流水线质量门告警:
public void ProcessLevels() { if(GetDistinctEmployers()) { foreach(string employer in AllLevels.Select(x => x.Employer)) { if(GetDistinctLevel1(employer)) { foreach(string level1 in AllLevels.Select(x => x.Level1)) { if(GetDistinctLevel2(level1)) { foreach(string level2 in AllLevels.Select(x => x.Level2)) { if(GetDistinctLevel3(level2)) { foreach(string level3 in AllLevels.Select(x => x.Level3)) { if(GetDistinctLevel4(level3)) { SaveData(); } } } } } } } } } }
同时代码质量提示指出AllLevels.Select(x => x.Employer)这类表达式可通过LINQ简化,但不清楚具体操作方式。期望输出为层级展开视图,包含从顶层到最底层的所有去重节点。
最终解决方案
参考建议后重构代码,消除大量嵌套循环,实现如下:
public void ProcessLevels() { var employers = AllLevels.Where(x=> !x.isExpired ).Select(x => x.Employer).Distinct(); var lvl1 = AllLevels.Where(x=> !x.isExpired ).Select(x => new {x.Employer, x.Level1 }).Distinct(); var lvl2 = AllLevels.Where(x=> !x.isExpired ).Select(x => new {x.Employer, x.Level1, x.Level2 }).Distinct(); var lvl3 = AllLevels.Where(x=> !x.isExpired ).Select(x => new {x.Employer, x.Level1, x.Level2, x.Level3 }).Distinct(); var lvl4 = AllLevels.Where(x=> !x.isExpired ).Select(x => new {x.Employer, x.Level1, x.Level2, x.Level3, x.Level4 }).Distinct(); foreach(var emp in employers) { LocationLevels.Add(new LevelHierarchyStructure(emp)); } foreach(var lvl in lvl1) { LocationLevels.Add(new LevelHierarchyStructure(lvl.Employer, lvl.Level1)); } foreach(var lvl in lvl2) { LocationLevels.Add(new LevelHierarchyStructure(lvl.Employer, lvl.Level1, lvl.Level2)); } foreach(var lvl in lvl3) { LocationLevels.Add(new LevelHierarchyStructure(lvl.Employer, lvl.Level1, lvl.Level2, lvl.Level3)); } foreach(var lvl in lvl4) { LocationLevels.Add(new LevelHierarchyStructure(lvl.Employer, lvl.Level1, lvl.Level2, lvl.Level3, lvl.Level4)); } SaveData(); }
内容的提问来源于stack exchange,提问作者Nyra
相关产品推荐
相关产品推荐

