C# 向<int,Individual>字典添加元素时如何避免pattern重复的对象
优化方案
核心思路是通过预计算pattern的稳定哈希值,结合哈希集合将查重复杂度从原有的O(n)降低到O(1),同时完全保留你原有population字典的int键逻辑。
步骤1:实现Pattern字典的自定义比较器
C#默认的Dictionary相等比较是引用比较,需要自定义比较器实现内容层面的相等判断:
public class PatternComparer : IEqualityComparer<Dictionary<int, int>> { public bool Equals(Dictionary<int, int> x, Dictionary<int, int> y) { // 优先比对数量,和原有逻辑一致 if (x.Count != y.Count) return false; foreach (var kvp in x) { if (!y.TryGetValue(kvp.Key, out var val) || val != kvp.Value) return false; } return true; } public int GetHashCode(Dictionary<int, int> obj) { var hash = new HashCode(); hash.Add(obj.Count); // 必须按key排序后计算哈希,避免相同内容的字典因遍历顺序不同生成不同哈希 foreach (var kvp in obj.OrderBy(k => k.Key)) { hash.Add(kvp.Key); hash.Add(kvp.Value); } return hash.ToHashCode(); } }
步骤2:新增哈希集合做快速查重
额外维护一个存储已存在pattern的哈希集合,和原有population字典同步更新:
// 全局初始化 private readonly PatternComparer _patternComparer = new PatternComparer(); // 快速查重用的哈希集合 private readonly HashSet<Dictionary<int, int>> _existingPatterns = new HashSet<Dictionary<int, int>>(new PatternComparer()); // 保留原有的population字典,用于其他模块关联 private readonly Dictionary<int, Individual> population = new Dictionary<int, Individual>();
步骤3:实现带查重的新增逻辑
// 新增Individual入口,返回是否添加成功 public bool TryAddIndividual(int populationKey, Individual newInd) { // 查重仅需O(1),只有哈希冲突时才会调用Equals做内容比对 if (_existingPatterns.Contains(newInd.pattern)) return false; // 两个集合同步更新,保证数据一致性 population.Add(populationKey, newInd); _existingPatterns.Add(newInd.pattern); return true; }
注意事项
- 如果
Individual的pattern字段创建后不会修改,上述方案可以直接使用,性能提升非常显著 - 如果
pattern后续会修改键值对,需要在修改前先从_existingPatterns中删除旧的pattern,修改完成后重新计算哈希再加入集合,避免哈希失效 - 对于性能要求极高的场景,可以在
Individual类中预存pattern的哈希值,修改pattern时同步更新预存值,进一步降低哈希计算的开销
内容的提问来源于stack exchange,提问作者33fred33
相关产品推荐
相关产品推荐

