从DataTable和自定义IEqualityComparer <DataRow>中删除重复项

aba*_*hev 6 .net c# linq datatable iequalitycomparer

我如何实现IEqualityComparer<DataRow>DataTable下一个结构中删除重复行:

ID primary key, col_1, col_2, col_3, col_4
Run Code Online (Sandbox Code Playgroud)

默认比较器不起作用,因为每行都有自己唯一的主键.

如何实现IEqualityComparer<DataRow>将跳过主键并仅比较剩余的数据.

我有这样的事情:

public class DataRowComparer : IEqualityComparer<DataRow>
{
 public bool Equals(DataRow x, DataRow y)
 {
  return
   x.ItemArray.Except(new object[] { x[x.Table.PrimaryKey[0].ColumnName] }) ==
   y.ItemArray.Except(new object[] { y[y.Table.PrimaryKey[0].ColumnName] });
 }

 public int GetHashCode(DataRow obj)
 {
  return obj.ToString().GetHashCode();
 }
}
Run Code Online (Sandbox Code Playgroud)

public static DataTable RemoveDuplicates(this DataTable table)
{
  return
    (table.Rows.Count > 0) ?
  table.AsEnumerable().Distinct(new DataRowComparer()).CopyToDataTable() :
  table;
}
Run Code Online (Sandbox Code Playgroud)

但它只打电话GetHashCode()而不打电话Equals()

Mik*_*Two 5

这是有效的方式Distinct.它本质上使用该GetHashCode方法.你可以写GetHashCode你做你需要的.就像是

public int GetHashCode(DataRow obj)
{
    var values = obj.ItemArray.Except(new object[] { obj[obj.Table.PrimaryKey[0].ColumnName] });
    int hash = 0;
    foreach (var value in values)
    {
        hash = (hash * 397) ^ value.GetHashCode();
    }
    return hash;
}
Run Code Online (Sandbox Code Playgroud)

由于您更了解数据,因此可能会想出一种更好的方法来生成哈希.

  • 这不仅仅是一个"好主意",而是推荐的做法.MSDN说,覆盖Equals的类型也必须覆盖GetHashCode." (3认同)
  • @abatishchev - 397就是ReSharper选择的.一个非常小的素数就可以了.我离开了主键,因为要点是在非主键列中找到重复项. (2认同)