在 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 行,那是您的失败。

通过首先检查单行的所有列并在符合删除条件时立即退出,您就完成了该行,无需考虑查看任何其他列。移至下一行进行处理。