在 C# 中删除列后循环数据表
Loop on datatable after deleting columns in C#
我正在尝试从数据表中删除具有空单元格或空单元格的行,同时我检查列中是否有超过百分比的空单元格,如果是这样,我将删除整列。我试过这样进行:
private DataTable CleanData()
{
var dt = BindData(openFileDialog1.FileName);
for (var j = dt.Columns.Count-1; j >= 0; j--)
{
short count = 0;
for (var i = dt.Rows.Count - 1; i >= 0; i--)
{
if (!string.IsNullOrEmpty(dt.Rows[i][j].ToString())) continue;
count++;
}
var percentage = count * 100.0 / dt.Rows.Count;
if (percentage > 10)
{
dt.Columns.RemoveAt(j);
textFile.Text += " " + j + " ";
}
}
dt.AcceptChanges();
for (var j = dt.Columns.Count - 1; j >= 0; j--)
for (var i = dt.Rows.Count - 1; i >= 0; i--)
{
if (!string.IsNullOrEmpty(dt.Rows[i][j].ToString())) continue;
dt.Rows[i].Delete();
}
dt.AcceptChanges();
return dt;
}
我第一次遍历数据表单元格,然后检查列中空单元格的百分比,如果它超过 10%,我删除该列,然后我第二次循环,这次删除每一行一个空单元格,但在第二个循环中,当它到达已删除的列索引时,我收到一条错误消息 (System.Data.DeletedRowInaccessibleException
),即使它应该在那些列不存在的数据表上循环。
有什么线索让我搞砸了吗?
编辑:我进行了建议的更改,但仍然出现相同的错误
我认为您 运行 是循环检查 % 和删除列的意外副作用。您从 0 索引列(第一列)开始。检查然后如果为空则删除。反过来做...从最后一列开始,然后回到 0,这就是原因。
假设您从 table 的 3 列开始,因此您的循环计数器旨在为 0、1、2。首先循环,循环计数器 0。您确定数据良好,不删除。计数器 = 1(第 2 列)。由于 % 为空,确定需要将其删除。现在您删除列 [1]。这移动了 WAS column[2],现在变成了 column[1],你的计数器现在前进到 2。你从来没有检查过第三列是什么。
如果你反过来,你从第[3]列开始,检查它,发现它可以(或不,不关心)。现在向下 1 到 column[2] 并确定删除。所以它被删除了,column[3] 现在是 column[2]。现在您检查第 [0] 列并完成没有问题。
您在检查 ROWS 时已经在执行此操作(从末尾开始并返回)。同样的原则也适用。
至于你删除 ROW 的循环,我会反转你的循环。
Outer loop per ROW (last row first, working back)
{
Inner loop per COLUMN
{
if any single column qualifies to delete the row
{
dt.rows[i].Delete();
break; [break out of the column checking loop]
}
}
[ continue with each ROW]
}
由于您现有的外循环是按列进行的,如果您处理第 1 列并删除第 5 行,然后转到第 2 列并尝试再次删除第 5 行,那是您的失败。
通过首先检查单行的所有列并在符合删除条件时立即退出,您就完成了该行,无需考虑查看任何其他列。移至下一行进行处理。
我正在尝试从数据表中删除具有空单元格或空单元格的行,同时我检查列中是否有超过百分比的空单元格,如果是这样,我将删除整列。我试过这样进行:
private DataTable CleanData()
{
var dt = BindData(openFileDialog1.FileName);
for (var j = dt.Columns.Count-1; j >= 0; j--)
{
short count = 0;
for (var i = dt.Rows.Count - 1; i >= 0; i--)
{
if (!string.IsNullOrEmpty(dt.Rows[i][j].ToString())) continue;
count++;
}
var percentage = count * 100.0 / dt.Rows.Count;
if (percentage > 10)
{
dt.Columns.RemoveAt(j);
textFile.Text += " " + j + " ";
}
}
dt.AcceptChanges();
for (var j = dt.Columns.Count - 1; j >= 0; j--)
for (var i = dt.Rows.Count - 1; i >= 0; i--)
{
if (!string.IsNullOrEmpty(dt.Rows[i][j].ToString())) continue;
dt.Rows[i].Delete();
}
dt.AcceptChanges();
return dt;
}
我第一次遍历数据表单元格,然后检查列中空单元格的百分比,如果它超过 10%,我删除该列,然后我第二次循环,这次删除每一行一个空单元格,但在第二个循环中,当它到达已删除的列索引时,我收到一条错误消息 (System.Data.DeletedRowInaccessibleException
),即使它应该在那些列不存在的数据表上循环。
我认为您 运行 是循环检查 % 和删除列的意外副作用。您从 0 索引列(第一列)开始。检查然后如果为空则删除。反过来做...从最后一列开始,然后回到 0,这就是原因。
假设您从 table 的 3 列开始,因此您的循环计数器旨在为 0、1、2。首先循环,循环计数器 0。您确定数据良好,不删除。计数器 = 1(第 2 列)。由于 % 为空,确定需要将其删除。现在您删除列 [1]。这移动了 WAS column[2],现在变成了 column[1],你的计数器现在前进到 2。你从来没有检查过第三列是什么。
如果你反过来,你从第[3]列开始,检查它,发现它可以(或不,不关心)。现在向下 1 到 column[2] 并确定删除。所以它被删除了,column[3] 现在是 column[2]。现在您检查第 [0] 列并完成没有问题。
您在检查 ROWS 时已经在执行此操作(从末尾开始并返回)。同样的原则也适用。
至于你删除 ROW 的循环,我会反转你的循环。
Outer loop per ROW (last row first, working back)
{
Inner loop per COLUMN
{
if any single column qualifies to delete the row
{
dt.rows[i].Delete();
break; [break out of the column checking loop]
}
}
[ continue with each ROW]
}
由于您现有的外循环是按列进行的,如果您处理第 1 列并删除第 5 行,然后转到第 2 列并尝试再次删除第 5 行,那是您的失败。
通过首先检查单行的所有列并在符合删除条件时立即退出,您就完成了该行,无需考虑查看任何其他列。移至下一行进行处理。