比较和删除数据表中所有相似行的方法

时间:2015-03-25 23:03:54

标签: c# datatable row

我正在尝试创建一个方法,给定一个表,将删除相似的行。我想做的是创建一个双foreach周期,以便表中的每一行都将与其他所有行进行比较。

private void comparaeapagarowsiguais(DataTable table1)
    {
        foreach (DataRow row1 in table1.Rows)
        {
            foreach (DataRow row2 in table1.Rows)
            {
                var array1 = row1.ItemArray;
                var array2 = row2.ItemArray;

                if (array1.SequenceEqual(array2))
                {
                    table1.Rows.Remove(row2);
                }

            }
        }


    }

问题在于,在某些时候,任何给定的行都将与自身进行比较,因此,将尝试删除自身(并且我将以完全没有行结束)。但我想保留至少每一行不同的一行。

我如何循环使用它们,同时避免任何给定的行与自己进行比较?

编辑:部分解决方案

我想出了一个适用于我的解决方案。如果相似的行全部紧挨着彼此,这将起作用。 (如果在表格周围有相似的行,则无效)

 private void comparalinhaseapaga(DataTable table1)
    {   //I will explain the try in the end
        try
        {
            //you will run i for as long as you like
            for (int i = 0; ; )
            {
                //you create 2 arrays from i, and i+1, this means you will compare
                //the first 2 lines of the data table
                var array1 = table1.Rows[i].ItemArray;
                var array2 = table1.Rows[i + 1].ItemArray;

                 //if they are similar, it removes row at 1, and will go back to the cycle and 
                 //proceed to compare row at 0 with the previously row at 2
                if (array1.SequenceEqual(array2))
                {
                    table1.Rows.RemoveAt(i + 1);
                }
                else
                {
                    //if they are not equal, it move next to row at 1, and compare it with row at 2
                    //once it gets here, the row 0 and row 1 are already different
                    //that's why it only works when the similar rows are adjacent to another
                    i++;
                }
            }
        }
        catch { }
    }

尝试和捕获是因为在某些时候他不会在位置i + 1处有一行进行比较,并且会产生错误。使用try / catch将跳过错误并继续,您可以执行此操作,因为已删除所有类似的行。经过测试和工作;)

希望这对某人有用。

编辑2: 找到一个干净的解决方案,只需使用此代码:

 private DataTable RemoveDuplicatesRecords(DataTable dt)
    {
        //Returns just unique rows
        var UniqueRows = dt.AsEnumerable().Distinct(DataRowComparer.Default);
        DataTable dt2 = UniqueRows.CopyToDataTable();
        return dt2;
    }

3 个答案:

答案 0 :(得分:2)

我认为这可以通过方法简化为一组,这只能通过使用linq来实现。然后只需选择每组的第一项

这会将您的数据表转换为可枚举的,然后允许您按照您不会重复的值进行分组

public IEnumerable<DataRow> test(DataTable myTable)
    {
        var results = myTable.AsEnumerable()
            .GroupBy(datarow => datarow .ItemArray[1]).Select(y=> y.First()) ;

        return results;
    }

或者如果它匹配所有字段

public DataTable test(DataTable myTable)
    {
        var results = myTable.AsEnumerable().Distinct().CopyToDataTable() ;

        return results;
    }

答案 1 :(得分:1)

您可以修改您的方法,添加以下检查

private void comparaeapagarowsiguais(DataTable table1)
{
    foreach (DataRow row1 in table1.Rows)
    {
        foreach (DataRow row2 in table1.Rows)
        {
            if (row1 != row2) 
            {
                var array1 = row1.ItemArray;
                var array2 = row2.ItemArray;

                if (array1.SequenceEqual(array2))
                {
                    table1.Rows.Remove(row2);
                }
            }
        }
    }
}

这样,如果是起始行,则不应比较它们;)

或者,您可以使用LINQ(就像我在评论中写的那样)使用此代码仅选择相似的行然后删除它们:

private void comparaeapagarowsiguais(DataTable table1)
{
    foreach (DataRow row1 in table1.Rows)
    {
        var toDelete = table1.AsEnumerable().Where(row => row.ItemArray.SequenceEqual(row1.ItemArray));

        foreach (DataRow r in toDelete)
        {
            table1.Rows.Remove(r);
        }
    }
}

答案 2 :(得分:1)

private void comparaeapagarowsiguais(DataTable table1)
    { int a=0; int b=0;
        foreach (DataRow row1 in table1.Rows)
        {  a++; 
           b=0;
            foreach (DataRow row2 in table1.Rows)
            {  b++;
                if(a!=b)
                 {
                var array1 = row1.ItemArray;
                var array2 = row2.ItemArray;

                if (array1.SequenceEqual(array2))
                {
                    table1.Rows.Remove(row2);
                }
               } 

            }
        }


    }