我正在尝试创建一个方法,给定一个表,将删除相似的行。我想做的是创建一个双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;
}
答案 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);
}
}
}
}
}