删除备忘录上的特定行



我有一个行中有不需要字符的备忘录,我想把它们全部删除。这是我的代码:

var
  del: Integer;
begin
  for del := 0 to m0.Lines.Count - 1 do
  begin
    if (AnsiContainsStr(m0.Lines[del], 'remove me')) then
    begin
      m0.Lines.Delete(del);
    end;
  end;
end;

上面的代码仍然留下了一些我想删除的行。它只删除了其中的一部分。所以我尝试了另一种方法,这就是做好工作。

var
  i, r, n: Integer;
begin
  for i := 0 to m0.Lines.Count - 1 do
  begin
    if (AnsiContainsStr(m0.Lines[i], 'remove me')) then
    begin
      for r := 0 to m0.Lines.Count - 1 do
      begin
        if (AnsiContainsStr(m0.Lines[r], 'remove me')) then
        begin
          for n := 0 to m0.Lines.Count - 1 do
          begin
            if (AnsiContainsStr(m0.Lines[n], 'remove me')) then
            begin
              m0.Lines.Delete(n);
            end;
          end;
          m0.Lines.Delete(r);
        end;
      end;
      m0.Lines.Delete(i);
    end;
  end;
end;

我认为这是不对的,我不应该这样做。如何优雅地完成这样的工作?

因为循环从0运行到Count - 1,所以删除行之后的行将被跳过。

说明:假设第3行需要删除。你删除它,现在第4行将是第3行。循环变量i将在下一次运行时增加到4,因此永远不会对新行3进行求值。

解决方案:反向运行循环:

for i := m0.Lines.Count - 1 downto 0 do

删除一行时,将更改所有后续行的索引。您尚未处理的行。您还可以使循环无效,因为一旦删除一行,for循环的上限就超出了界限。您的第一个代码块读取的内容超出了列表的末尾。

考虑一个有3行的列表。你看第一行,索引0,然后选择删除它。现在还剩两行。接下来,您需要查看原始列表中的第1行和第2行,但它们现在编号为0和1。你的循环不起作用。您将跳过新索引为0的行。

标准的技巧是按相反的顺序处理列表。然后,当您删除一个项目时,其索引更改的行已经被处理。在伪代码中:

for i := Count-1 downto 0 do
  if DeleteThisItem(i) then
    Delete(i);

关键是,无论何时使用索引i,都是指在循环开始之前具有索引i的项。

此任务要求采用另一种方法A for cycle将动态地减少行索引,并导致删除行之后的行被跳过,因为它们的索引会减少。


你应该使用while循环来代替:

intIndex := 0; // starting at the first line
while intIndex < m0.Lines.Count do // iterating 'till the last line
begin
  if (AnsiContainsStr(m0.Lines[intIndex], 'remove me')) then // if the current line contains the text
    m0.Lines.Delete(intIndex) // delete that line and DON'T increase the index
  else
    Inc(intIndex); // increase the index
end;

相关内容

  • 没有找到相关文章

最新更新