删除备忘录中的特定行

时间:2014-10-26 08:03:33

标签: string delphi lines tmemo

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

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;

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

3 个答案:

答案 0 :(得分:8)

由于您的循环从0运行到Count - 1,因此将跳过删除行之后的行。

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

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

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

答案 1 :(得分:3)

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

考虑一个包含3行的列表。您查看第一行索引0,然后选择删除它。现在剩下两行。接下来需要查看原始列表中的第1行和第2行,但它们现在编号为0和1.您的循环将无法执行此任务。您将跳过新索引为0的行。

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

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

关键是每当你使用索引i时,你指的是在循环开始之前索引为i的项目。

答案 2 :(得分:2)

此任务要求另一种方法。 for循环将动态地修改行索引并导致删除删除后的行,因为它们的索引会减少。


您应该使用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;