C# 从具有多列的数据表中删除重复项的最佳方法是什么

C# 从具有多列的数据表中删除重复项的最佳方法是什么,c#,C#,对于多列,从数据表中删除重复项的最佳方法是什么?我的意思是下面的代码仅适用于单列 public DataTable RemoveDuplicateRows(DataTable dTable, string colName) { Hashtable hTable = new Hashtable(); ArrayList duplicateList = new ArrayList(); //Add list of all the unique item value to hash

对于多列,从数据表中删除重复项的最佳方法是什么?我的意思是下面的代码仅适用于单列

public DataTable RemoveDuplicateRows(DataTable dTable, string colName)
{
   Hashtable hTable = new Hashtable();
   ArrayList duplicateList = new ArrayList();

   //Add list of all the unique item value to hashtable, which stores combination of key, value pair.
   //And add duplicate item value in arraylist.
   foreach (DataRow drow in dTable.Rows)
   {
      if (hTable.Contains(drow[colName]))
         duplicateList.Add(drow);
      else
         hTable.Add(drow[colName], string.Empty); 
   }

   //Removing a list of duplicate items from datatable.
   foreach (DataRow dRow in duplicateList)
      dTable.Rows.Remove(dRow);

   //Datatable which contains unique records will be return as output.
      return dTable;
}
我尝试使用字符串[]colName。它在
dTable.Rows.Remove(dRow)处抛出错误


请建议。

您可以在Datatable上使用Distinct。选择


参考此

最简单、最易读的方法是使用
Linq to DataTable

var groups = from r in dTable.AsEnumerable()
             group r by new
             {
                 Col1 = r.Field<String>("Column1"),
                 Col2 = r.Field<String>("Column2"),
             };

// if you only want the first row of each group:
DataTable distinctTable = groups.Select(g => g.First()).CopyToDataTable();
您的
RemoveDuplicateRows
方法:

public DataTable RemoveDuplicateRows(DataTable dTable, String[] colNames)
{
    var hTable = new Dictionary<object[], DataRow>(new ObjectArrayComparer());

    foreach (DataRow drow in dTable.Rows)
    {
        Object[] objects = new Object[colNames.Length];
        for (int c = 0; c < colNames.Length; c++)
            objects[c] = drow[colNames[c]];
        if (!hTable.ContainsKey(objects))
            hTable.Add(objects, drow);
    }

    // create a clone with the same columns and import all distinct rows
    DataTable clone = dTable.Clone();
    foreach (var kv in hTable)
        clone.ImportRow(kv.Value);

    return clone;
}
public DataTable RemoveDuplicateRows(DataTable dTable,String[]colNames)
{
var hTable=newdictionary(newObjectArrayComparer());
foreach(dTable.Rows中的数据行drow)
{
Object[]objects=新对象[colNames.Length];
for(int c=0;c
测试:

var table = new DataTable();
table.Columns.Add("Colum1", typeof(string));
table.Columns.Add("Colum2", typeof(int));
table.Columns.Add("Colum3", typeof(string));

Random r = new Random();
for (int i = 0; i < 100; i++)
{
    table.Rows.Add("Colum1_" + r.Next(1, 10), r.Next(1, 10), "Colum3_" + r.Next(1, 10));
}
int rowCount = table.Rows.Count; // 100
var unique = RemoveDuplicateRows(table, new[] { "Colum1", "Colum2" });
int uniqueRowCount = unique.Rows.Count; // around 55-65
var table=newdatatable();
表.Columns.Add(“Colum1”,typeof(string));
表.列.添加(“列2”,类型(int));
表.Columns.Add(“Colum3”,typeof(string));
随机r=新随机();
对于(int i=0;i<100;i++)
{
表.行.添加(“列1_”+r.Next(1,10),r.Next(1,10),“列3_”+r.Next(1,10));
}
int rowCount=table.Rows.Count;//100
var unique=RemoveDuplicateRows(表,新[]{“Colum1”,“Colum2”});
int uniqueRowCount=unique.Rows.Count;//大约55-65岁

以下是您的代码,并对我的代码进行了几处修改。
其主要思想是向
哈希表
(我的代码中的字典)中添加的不是一列的值,而是指定列的值,并以原子方式威胁这些值(就像单个值一样)

//您的代码只需稍加修改
公共DataTable RemovedUpplicateRows(DataTable dTable,string[]colNames)
{
//请注意,强类型字典已替换哈希表+它使用自定义比较器
var hTable=新字典();
var duplicateList=新的ArrayList();
//将所有唯一项值的列表添加到哈希表中,哈希表存储键、值对的组合。
//并在arraylist中添加重复的项值。
foreach(dTable.Rows中的数据行drow)
{
var dataRowInfo=新的dataRowInfo(drow,colNames);
if(hTable.ContainsKey(dataRowInfo))
重复列表。添加(drow);
其他的
添加(dataRowInfo,string.Empty);
}
//从datatable中删除重复项的列表。
foreach(重复列表中的数据行dRow)
dTable.Rows.Remove(dRow);
//包含唯一记录的Datatable将作为输出返回。
返回数据表;
}
//助手类
//包含指定列的值
内部密封类DataRowInfo
{
公共对象[]值{get;private set;}
公共DataRowInfo(DataRow DataRow,string[]列)
{
Values=columns.Select(c=>dataRow[c]).ToArray();
}
公共覆盖布尔等于(对象对象对象)
{
if(ReferenceEquals(this,obj))
返回true;
var other=对象作为数据行信息;
如果(其他==null)
返回false;
回报等于(其他);
}
私有布尔等于(DataRowInfo其他)
{
if(this.Values.Length!=其他.Values.Length)
返回false;
for(int i=0;i
希望这会有所帮助

更新
代码简化了一点。

:谢谢你的回答。我真的不明白这里的概念。我们在哪里删除重复项???@user1495475:添加了一些希望有用的注释。Tim:汇编缺少“AsEnumerable”。我尝试包含system.data.datatable仍然是相同的错误。有什么问题吗?@user1495475:您是否至少使用了.NET 35,并且是否添加了对
system.data.DataSetExtensions.dll
的引用?Tim:I
m使用目标框架作为版本2.0。我还没有使用您的参考system.data.DataSetExtensions,阿列克西:谢谢你的回答。我不认为这是一个更好的方法。我们没有一个简单的方法来解决这个问题吗???@user1495475:我已经简化了一些代码,恐怕我不能做更简单的事情了。顺便说一句,尽管该解决方案的代码比您发布的要多得多,但它并没有那个么复杂:它只是将值添加到哈希表数组(包装到helper数据结构中),而不是单个原语值。讨厌重新发布我自己的答案。看见
var table = new DataTable();
table.Columns.Add("Colum1", typeof(string));
table.Columns.Add("Colum2", typeof(int));
table.Columns.Add("Colum3", typeof(string));

Random r = new Random();
for (int i = 0; i < 100; i++)
{
    table.Rows.Add("Colum1_" + r.Next(1, 10), r.Next(1, 10), "Colum3_" + r.Next(1, 10));
}
int rowCount = table.Rows.Count; // 100
var unique = RemoveDuplicateRows(table, new[] { "Colum1", "Colum2" });
int uniqueRowCount = unique.Rows.Count; // around 55-65
            // your code with minor amends
    public DataTable RemoveDuplicateRows(DataTable dTable, string[] colNames)
    {
        // note that strongly typed dictionary has replaced the hash table + it uses custom comparer 
        var hTable = new Dictionary<DataRowInfo, string>();
        var duplicateList = new ArrayList();

        //Add list of all the unique item value to hashtable, which stores combination of key, value pair.
        //And add duplicate item value in arraylist.
        foreach (DataRow drow in dTable.Rows)
        {
            var dataRowInfo = new DataRowInfo(drow, colNames);

            if (hTable.ContainsKey(dataRowInfo))
                duplicateList.Add(drow);
            else
                hTable.Add(dataRowInfo, string.Empty);
        }

        //Removing a list of duplicate items from datatable.
        foreach (DataRow dRow in duplicateList)
            dTable.Rows.Remove(dRow);

        //Datatable which contains unique records will be return as output.
        return dTable;
    }

    // Helper classes

    // contains values of specified columns
    internal sealed class DataRowInfo
    {
        public object[] Values { get; private set; }

        public DataRowInfo(DataRow dataRow, string[] columns)
        {
            Values = columns.Select(c => dataRow[c]).ToArray();
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(this, obj))
                return true;

            var other = obj as DataRowInfo;
            if (other == null)
                return false;

            return Equals(other);
        }

        private bool Equals(DataRowInfo other)
        {
            if (this.Values.Length != other.Values.Length)
                return false;
            for (int i = 0; i < this.Values.Length; i++)
            {
                if (AreObjectsEqual(this.Values[i], other.Values[i]))
                    return false;
            }

            return true;
        }

        private static bool AreObjectsEqual(object left, object right)
        {
            if (ReferenceEquals(left, right))
                return true;

            if (ReferenceEquals(left, null))
                return false;

            if (ReferenceEquals(right, null))
                return false;

            if (left.GetType() != right.GetType())
                return false;

            return left.Equals(right);
        }

        public override int GetHashCode()
        {
            unchecked
            {
                int hashCode = 0;
                foreach (var value in this.Values)
                {
                    hashCode = hashCode ^ ((value != null ? value.GetHashCode() : 0) * 397);
                }
                return hashCode;
            }
        }
    }