入门级的问题,TStringGrid 删除数据行的代码写法优化(50)

  • 主题发起人 主题发起人 delhpi
  • 开始时间 开始时间
D

delhpi

Unregistered / Unconfirmed
GUEST, unregistred user!
有个TStringGrid,第一行是标题行,第一行、第一列是固定的。第一列是行序号列,另外的列中有一列是“姓名”列。另外已知一个TStringList实例nameList,并且Sorted:=true;Duplicates := dupIgnore;里面已经有若干项,比如有张三,李四等。现在要将Stringgrid中,“姓名”列中的值在nameList中的所有行删除。下面是我的山寨代码,功能是实现了。想请教大家,想学习一下更正规一点的代码。var i, S, j, F: integer; beginwith SgSend do begin for i := 1 to RowCount - 1 do if NameList.Find(Cells[NameCol, i], F) then rows.Clear; s := 0; for i := 1 to rowCount - 1 do if length(cells[0, i]) = 0 then //这行是空白 if s < RowCount - 1 then //上次查找 没有到末尾 for j := i + 1 to rowCount - 1 do //从下面开始找一非空行 begin if j = RowCount - 1 then s := j; if length(cells[0, j]) > 0 then //应该保留的行 begin rows.Assign(rows[j]); cells[0, i] := inttostr(i); rows[j].Clear; break; end; end; for i := RowCount - 1 downto 1 do if length(Cells[0, i]) = 0 then begin if RowCount >2 then RowCount := RowCount - 1; end; end;end;
 
你的数据是从哪里来的?应该直接在数据源里查找,在数据源里判断,要删除或只取出符合你条件的数据。
 
我不是用的数据库。
 
procedure RemoveARow(gd:TStringGrid;Row: Integer); //删除行var aRow: Integer;begin if Row < gd.RowCount then begin for aRow := Row to gd.RowCount-1 do gd.Rows[aRow].Assign(gd.Rows[aRow+1]); end;end;
 
楼上的意思是 用这个通用的procedure在需要的地方来一行一行删除。procedure TForm1.Button1Click(Sender: TObject);var r: Integer;begin with StringGrid1 do begin for r := RowCount - 1 downto 1 do if cells[2,r]='1' then//假设 判断的条件是 值为1 begin RemoveARow(StringGrid1,r); if RowCount > 2 then rowcount:=RowCount-1; end; end;end;
 
用那个procedure虽然很简洁,但是好象数据行的挪动次数很多。比如共10 000条记录,满足删除条件的是1-10行。当先删除第10行,需要挪动(10 000-10)行接下来删除第9行,需要再次挪动(10 1000-9)行。。最后删除第1行时,需要挪动(10 000-1)行。随便说说,不要见外。
 
刚才测试了一下,10 000行,满足删除条件的是1-100行。我的代码,似乎在速度上快很多,30倍以上差异 。如果满足删除条件的是1-1000行。速度差异就更大了。如果满足删除条件的是最后1000行,2者速度相当。==我的代码=====procedure TForm1.Button3Click(Sender: TObject);var i, S, j, F: integer; A: Cardinal;begin A := GetTickCount(); with StringGrid1 do begin for i := 1 to RowCount - 1 do if Cells[2, i] = '1' then//假设删除条件是值=1 rows.Clear; s := 0; for i := 1 to rowCount - 1 do if length(cells[0, i]) = 0 then //这行是空白 if s < RowCount - 1 then //上次查找 没有到末尾 for j := i + 1 to rowCount - 1 do //从下面开始找一非空行 begin if j = RowCount - 1 then s := j; if length(cells[0, j]) > 0 then //应该保留的行 begin rows.Assign(rows[j]); cells[0, i] := inttostr(i); rows[j].Clear; break; end; end; for i := RowCount - 1 downto 1 do if length(Cells[0, i]) = 0 then begin if RowCount > 2 then RowCount := RowCount - 1; end; end; MEMO1.Lines.Add(INTTOSTR(GetTickCount - A));end;==用那个删除procedure=========procedure TForm1.Button2Click(Sender: TObject);var r: Integer; A: Cardinal;begin A := GetTickCount; with StringGrid1 do begin for r := RowCount - 1 downto 1 do if cells[2, r] = '1' then//假设删除条件是值=1 begin RemoveARow(StringGrid1, r); if RowCount > 2 then rowcount := RowCount - 1; end; end; MEMO1.Lines.ADD(INTTOSTR(GetTickCount - A));end;
 
自己又想到一种方式,速度更快。10 000行数据,删除前面1000行,我电脑上只要0.15秒。procedure TForm1.Button4Click(Sender: TObject);var i, R, S, j, F: integer; A: Cardinal; StrList: TStringList;begin A := GetTickCount(); with StringGrid1 do begin strlist := TStringList.Create; try for i := 1 to RowCount - 1 do if Cells[2, i] <> '1' then //留下的 strlist.Add(inttostr(i)) else rows.Clear; for i := 0 to strList.Count - 1 do begin r := strtoint(strlist); rows[i + 1].Assign(rows[R]); ROWS[R].Clear; CELLS[0, i + 1] := inttostr(i + 1); end; if strlist.Count>0 then RowCount:=strlist.Count+1 else rowcount := 2; finally strlist.free; end; end; MEMO1.Lines.Add(INTTOSTR(GetTickCount - A));end;
 
接受答案了.
 
后退
顶部