基于指定列对DataTable去重遇问题:现有代码无返回值求协助
问题分析
你原代码的逻辑完全错误:DistinctBy的key是判断表列集合是否包含拼接后的列名字符串,得到的是布尔值。如果所有行的这个判断结果一致,最终只会留一行;若判断结果为false则返回空数组,这和按指定列去重的需求完全不符。
解决方案
推荐三种可行的实现方式,按推荐程度排序:
1. 使用DataView原生去重(最简洁高效)
DataTable原生提供了通过DataView.ToTable实现按指定列去重的方法,无需手动处理比较逻辑:
// 创建DataView DataView dataView = new DataView(dataTable1); // 调用ToTable,第一个参数true表示去重,第二个参数传入要去重的列名数组 DataTable distinctTable = dataView.ToTable(true, columnsToBeUnique); // 转换为DataRow数组 var result = distinctTable.AsEnumerable().ToArray();
2. 自定义数组比较器配合DistinctBy
如果需要用Linq的方式实现,可以通过自定义数组比较器,将指定列的值数组作为去重依据:
首先实现数组比较器(用于正确比较值数组的内容):
public class ArrayEqualityComparer<T> : IEqualityComparer<T[]> { public bool Equals(T[] x, T[] y) { if (x == null && y == null) return true; if (x == null || y == null) return false; if (x.Length != y.Length) return false; for (int i = 0; i < x.Length; i++) { if (!EqualityComparer<T>.Default.Equals(x[i], y[i])) return false; } return true; } public int GetHashCode(T[] obj) { if (obj == null) return 0; int hash = 17; foreach (var item in obj) { hash = hash * 31 + (item?.GetHashCode() ?? 0); } return hash; } }
然后使用Linq去重:
var result = dataTable1 .AsEnumerable() .DistinctBy(row => columnsToBeUnique.Select(col => row[col]).ToArray(), new ArrayEqualityComparer<object>()) .ToArray();
3. 序列化列值为字符串(简单但性能一般)
如果数据量不大,可以将指定列的值序列化为唯一字符串作为去重键,利用JSON序列化即可:
using System.Text.Json; var result = dataTable1 .AsEnumerable() .DistinctBy(row => JsonSerializer.Serialize(columnsToBeUnique.Select(col => row[col]))) .ToArray();
注意:若列值中包含特殊字符,序列化能保证键的唯一性,但大数据量下性能不如前两种方法。
内容的提问来源于stack exchange,提问作者Rico Strydom
相关产品推荐
相关产品推荐

