如何在128位BitArray数组中查找重复元素?
查找128位BitArray数组中的重复元素
看你写的代码,应该是卡在用int数组作为字典键的环节了吧?其实你的思路方向没问题,但有几个小坑需要注意——比如int数组是引用类型,字典默认会比较引用而不是数组内容,这样就算两个数组内容完全一样,也会被当成不同的键;另外把BitArray转成二进制字符串再转字节数组的步骤,其实有点多余,效率也不高。
我给你几个更靠谱的解决方案,你可以根据自己的需求选:
方案一:转成两个Long作为键(高效首选)
因为每个BitArray是128位,正好可以拆成两个64位的long(一个存高64位,一个存低64位),用这两个long的组合作为字典的键,既能保证唯一性,又能高效计算:
BitArray[] bitsarr = // 你的BitArray数组 // 用ValueTuple作为键(C#7.0及以上支持,比Tuple更简洁) var countDict = new Dictionary<(long HighBits, long LowBits), int>(); foreach (var bitArray in bitsarr) { // 先校验每个BitArray的长度是否是128位 if (bitArray.Length != 128) { Console.WriteLine("跳过长度不符合的BitArray"); continue; } // 直接把BitArray转成16字节的数组(不用转字符串!) byte[] byteArr = new byte[16]; bitArray.CopyTo(byteArr, 0); // 拆分字节数组为两个long long highBits = BitConverter.ToInt64(byteArr, 0); long lowBits = BitConverter.ToInt64(byteArr, 8); var key = (HighBits: highBits, LowBits: lowBits); // 统计出现次数 if (countDict.ContainsKey(key)) { countDict[key]++; } else { countDict[key] = 1; } } // 筛选出重复的元素 var duplicateEntries = countDict.Where(kv => kv.Value > 1).ToList(); // 输出结果 foreach (var entry in duplicateEntries) { Console.WriteLine($"对应BitArray组合出现了 {entry.Value} 次,高64位:{entry.Key.HighBits},低64位:{entry.Key.LowBits}"); }
这个方法的优势是速度快,因为BitConverter.ToInt64是底层高效实现,比遍历字符串或者BitArray每一位要快得多。
方案二:自定义BitArray相等比较器
如果你想直接用BitArray作为字典的键,那需要自定义一个相等比较器,因为默认的BitArrayEquals方法只比较引用,不比较内容:
// 自定义BitArray的相等比较器 public class BitArrayEqualityComparer : IEqualityComparer<BitArray> { public bool Equals(BitArray x, BitArray y) { // 长度不同直接不相等 if (x.Length != y.Length) return false; // 逐位比较内容 for (int i = 0; i < x.Length; i++) { if (x[i] != y[i]) return false; } return true; } public int GetHashCode(BitArray obj) { // 生成哈希值,这里用简单的累加方式,你也可以用更复杂的哈希算法 int hash = 17; for (int i = 0; i < obj.Length; i++) { hash = hash * 31 + (obj[i] ? 1 : 0); } return hash; } } // 使用示例 BitArray[] bitsarr = // 你的BitArray数组 var countDict = new Dictionary<BitArray, int>(new BitArrayEqualityComparer()); foreach (var bitArray in bitsarr) { if (countDict.ContainsKey(bitArray)) { countDict[bitArray]++; } else { countDict[bitArray] = 1; } } // 查找重复元素 var duplicates = countDict.Where(kv => kv.Value > 1).Select(kv => kv.Key).ToList();
这个方法的优点是代码更直观,直接操作BitArray本身,但缺点是逐位计算哈希的速度会比方案一慢一些,适合BitArray数量不多的场景。
对你原有代码的修正
如果你坚持想用自己的思路,那需要把int数组转换成可以比较内容的类型,比如把byte数组转成一个唯一字符串作为键:
BitArray[] bitsarr = // 你的BitArray数组 var dict = new Dictionary<string, int>(); foreach (var bitArray in bitsarr) { if (bitArray.Length != 128) continue; byte[] bytes = new byte[16]; bitArray.CopyTo(bytes, 0); // 把字节数组转成唯一的字符串作为键 string key = BitConverter.ToString(bytes); if (dict.ContainsKey(key)) { dict[key]++; } else { dict[key] = 1; } }
不过还是更推荐方案一,性能和可读性都更好。
内容的提问来源于stack exchange,提问作者Yussra
相关产品推荐
相关产品推荐

