如何在Dictionary中处理重复键生成逗号分隔字符串?求替代方案
按键合并键值对的最优实现方案
我有一个List<string>类型的输入数据,每个元素是用&分隔的多组键值对筛选条件。需要把这些键值对按键归类,当键重复时,把对应的值合并成带括号的逗号分隔字符串。想知道实现这个需求的最优方式是什么?有没有Dictionary<string, string>的替代方案?有的话愿意尝试。
当前代码在键已存在时会报错,没法生成目标格式。以下是输入、预期输出和当前代码示例:
输入:
var input = new List<string> { "Location=COL&StockNumber=1111150416", "Location=NYC&StockNumber=2222250416&Invoice=Part", "Location=NYC&StockNumber=2222250416&Invoice=Part&Supplier=AutoZone" };
预期输出:
var output = new Dictionary<string, string> { { "Location", "(COL, NYC)" }, { "StockNumber", "(1111150416, 2222250416, 2222250417)" }, { "Invoice", "(Part)" }, { "Supplier", "(AutoZone)" } };
当前问题:
- 键已存在时,当前代码会抛出错误,无法生成带括号的逗号分隔值格式
当前代码:
var testDictionary = new Dictionary<string, string>(); for(var i = 0; i < keys.Count; i++) { var items = keys[i].Split("&"); for (var j = 0; j < items.Length; j++) { var data = items[j].Split("="); if (testDictionary.ContainsKey(data[0])) { testDictionary[data[0]] = // 不知道怎么在这里添加逗号分隔的值 } testDictionary.Add(data[0], data[1]); } }
一、改进Dictionary<string, string>实现
当前代码的核心问题是直接调用Add方法,忽略了键已存在的情况。正确思路是先收集同键的所有值(可选去重),最后再统一格式化为带括号的字符串。
示例代码:
// 先用Dictionary存每个键对应的所有值(HashSet自动去重) var tempDict = new Dictionary<string, HashSet<string>>(); foreach (var line in input) { var keyValuePairs = line.Split('&'); foreach (var kvp in keyValuePairs) { var parts = kvp.Split('='); if (parts.Length != 2) continue; // 跳过格式无效的键值对 var key = parts[0]; var value = parts[1]; if (!tempDict.ContainsKey(key)) { tempDict[key] = new HashSet<string>(); } tempDict[key].Add(value); } } // 转换为最终需要的格式 var output = tempDict.ToDictionary( kv => kv.Key, kv => $"({string.Join(", ", kv.Value)})" );
优点:
- 用
HashSet自动去重,避免同一个键下出现重复值 - 分步处理逻辑清晰,容错性强(能跳过无效格式的键值对)
- 手动控制集合操作,灵活性高
二、替代方案:使用Lookup<string, string>
.NET原生的Lookup<TKey, TElement>是专门为一键多值场景设计的集合类型,比手动用Dictionary存集合更简洁高效。
示例代码:
// 扁平化所有有效键值对 var allValidKvp = input.SelectMany(line => line.Split('&').Select(kvp => { var parts = kvp.Split('='); return parts.Length == 2 ? (Key: parts[0], Value: parts[1]) : default; }) ).Where(kvp => kvp.Key != null); // 创建Lookup分组 var lookup = allValidKvp.ToLookup(kvp => kvp.Key, kvp => kvp.Value); // 转换为目标格式 var output = lookup.ToDictionary( group => group.Key, group => $"({string.Join(", ", group.Distinct())})" );
优点:
- 原生支持一键多值分组,代码更简洁
- 内部实现经过优化,分组效率更高
- 只读特性避免意外修改,适合数据分组场景
三、性能与场景选择
- 如果需要频繁修改分组数据,优先选
Dictionary<HashSet<string>>,灵活性更强 - 如果是一次性分组需求,
Lookup的代码更简洁,性能表现更稳定 - 若不需要去重,可以把
HashSet换成List<string>,或去掉Distinct(),进一步提升性能
内容的提问来源于stack exchange,提问作者GThree
相关产品推荐
相关产品推荐

