C#中两种生成逆字典的实现代码是否输出相同结果?
两段逆字典生成代码是否等价?
现有一个姓名映射至电话号码的字典(存在重复号码的情况),需要生成将号码映射至姓名列表的逆字典。分别实现了以下两个版本的ToInverseDictionary方法,询问这两段代码是否会产生相同的结果:
版本1:foreach循环实现
private static IDictionary<T, IList<U>> ToInverseDictionary<T, U>(IDictionary<U, T> dictionary) { var inverseDictionary = new Dictionary<T, IList<U>>(); foreach (var objU in dictionary.Keys) { var objT = dictionary[objU]; if (inverseDictionary.TryGetValue(objT, out var objsUExisting)) { objsUExisting.Add(objU); } else { var objsU = new List<U>(); objsU.Add(objU); inverseDictionary[objT] = objsU; } } return inverseDictionary; }
版本2:LINQ实现
private static IDictionary<T, IList<U>> ToInverseDictionary<T, U>(IDictionary<U, T> dictionary) { return dictionary.GroupBy(kvp => kvp.Value).ToDictionary(grouping => grouping.Key, grouping => grouping.Select(g => g.Key).ToList()); }
结论
是的,这两段代码会产生完全相同的结果,逻辑完全等价。拆解LINQ版本的执行逻辑就能明白:
GroupBy(kvp => kvp.Value):把原字典的所有键值对(姓名-号码)按照Value(即电话号码)分组,每个分组的Key是电话号码,分组内包含所有原字典中映射到该号码的键值对。ToDictionary(...):将分组转换为目标逆字典:- 字典的
Key直接取用分组的Key(电话号码); - 字典的
Value是从分组的每个键值对里提取Key(姓名),再转成List<U>——这和foreach循环里逐个把姓名添加到对应号码列表的逻辑完全一致。
- 字典的
额外细节:
- 两者生成的姓名列表顺序一致:.NET中
Dictionary.Keys的遍历顺序,加上GroupBy保持原序列顺序的特性,会让姓名列表里的元素顺序和原字典中键的顺序完全相同; - 对重复号码的处理逻辑毫无差别:所有映射到同一号码的姓名都会被收集到同一个列表里。
内容的提问来源于stack exchange,提问作者Pavel Foltyn
相关产品推荐
相关产品推荐

