C#中如何从多层嵌套Dictionary获取数据(支持无/部分键)
C# 多层嵌套字典的灵活查询实现
我需要在C#中从多层嵌套的Dictionary中获取数据,当前字典结构如下:
static Dictionary<int, Dictionary<string, Dictionary<string, Dictionary<string, string>>>> allOffset = new();
需求
- 不传入任何键时,获取所有底层的字符串值
- 传入部分层级的键时,获取对应层级下的所有值
示例数据
{ (2024, ("B1", ("C1", ("E1", "Employee1")))), (2024, ("B1", ("C1", ("E2", "Employee2")))) }
预期输出
- 传入键
2024,或2024、B1、C1时,返回两条记录:"Employee1"和"Employee2" - 传入完整键
2024、B1、C1、E1时,仅返回"Employee1" - 不传入任何键时,返回两条记录:
"Employee1"和"Employee2"
测试数据填充代码
public void FillDummyData() { for (int i = 2022; i <= 2024; i++) { for (int j = 1; j <= 12; j++) { for(int k = 1; k <= 7; k++) { // 假设EmployeeData是封装allOffset添加逻辑的方法 EmployeeData.Add(i, j.ToString(), k.ToString(), $"{i}-{j}-{k}"); } } } }
之前查过相关资料,但仅覆盖两层嵌套的场景,不确定如何处理4层及更多层的情况。如果嵌套字典无法满足需求,也可以改用其他集合类型。
解决方案
方案一:基于现有嵌套字典实现灵活查询
编写重载方法,根据传入键的数量逐层遍历字典,收集对应层级的所有值:
public static IEnumerable<string> GetValues(int? key1 = null, string key2 = null, string key3 = null, string key4 = null) { // 初始遍历源:最外层字典 var currentLevel = allOffset.AsEnumerable(); // 过滤第一层键 if (key1.HasValue) { currentLevel = currentLevel.Where(kv => kv.Key == key1.Value); if (!currentLevel.Any()) yield break; } // 进入第二层并过滤 var level2 = currentLevel.SelectMany(kv => kv.Value.AsEnumerable()); if (!string.IsNullOrEmpty(key2)) { level2 = level2.Where(kv => kv.Key == key2); if (!level2.Any()) yield break; } // 进入第三层并过滤 var level3 = level2.SelectMany(kv => kv.Value.AsEnumerable()); if (!string.IsNullOrEmpty(key3)) { level3 = level3.Where(kv => kv.Key == key3); if (!level3.Any()) yield break; } // 进入第四层并过滤 var level4 = level3.SelectMany(kv => kv.Value.AsEnumerable()); if (!string.IsNullOrEmpty(key4)) { level4 = level4.Where(kv => kv.Key == key4); if (!level4.Any()) yield break; } // 返回最终值 foreach (var kv in level4) { yield return kv.Value; } }
使用示例:
// 无键查询 var allValues = GetValues().ToList(); // 传入第一层键 var year2024Values = GetValues(2024).ToList(); // 传入前三层键 var specificValues = GetValues(2024, "B1", "C1").ToList(); // 传入完整键 var singleValue = GetValues(2024, "B1", "C1", "E1").ToList();
方案二:改用扁平结构的集合(更推荐,适配多层扩展)
如果后续可能扩展到5、6层嵌套,嵌套字典会大幅提升代码复杂度,建议改用扁平实体类集合,将多层键作为实体属性:
// 定义实体类 public class EmployeeRecord { public int Year { get; set; } public string BKey { get; set; } public string CKey { get; set; } public string EKey { get; set; } public string Value { get; set; } } // 用List<EmployeeRecord>替代嵌套字典 static List<EmployeeRecord> allRecords = new();
填充数据方法:
public void FillDummyData() { for (int i = 2022; i <= 2024; i++) { for (int j = 1; j <= 12; j++) { for(int k = 1; k <= 7; k++) { allRecords.Add(new EmployeeRecord { Year = i, BKey = j.ToString(), CKey = k.ToString(), EKey = $"E{k}", // 补充E层键逻辑 Value = $"{i}-{j}-{k}" }); } } } }
查询方法:
利用LINQ灵活组合条件,适配任意层级的键查询:
public static IEnumerable<string> GetRecords(int? year = null, string bKey = null, string cKey = null, string eKey = null) { var query = allRecords.AsQueryable(); if (year.HasValue) query = query.Where(r => r.Year == year.Value); if (!string.IsNullOrEmpty(bKey)) query = query.Where(r => r.BKey == bKey); if (!string.IsNullOrEmpty(cKey)) query = query.Where(r => r.CKey == cKey); if (!string.IsNullOrEmpty(eKey)) query = query.Where(r => r.EKey == eKey); return query.Select(r => r.Value); }
该方案优势:
- 代码可读性、可维护性更高
- 扩展更多层级时,只需新增实体属性和查询条件
- 支持更复杂的查询组合(如范围查询、模糊匹配)
内容的提问来源于stack exchange,提问作者maulik kansara
相关产品推荐
相关产品推荐

