做点小贡献,我写的使用二分查找的DataSetLocateEx数.

superyys 2005-10-10 04:02:53
某些TDataSet,对于已按某字段排序的DataSet,在进行Locate时并没有使用二分查询、线性插值查找等高效查找算法。因为程序需要,所以自己写了一个,愿与大家一起分享。本函数只能完全等值匹配,不支持部分匹配、忽略大小写匹配,如果需要这两种模式,还是调用TdataSet.Locate。

function DataSetLocateEx(ADataSet: TDataSet; AFieldNames: string; vals: Variant; IsAsc: boolean): boolean;
label
JumpoutMainLoop;
var
top, bottom: int64;
ccc: int64;
Find: boolean;
Index: integer;
ControlsDisabled: boolean;
Fields: TList;
val: Variant;
OldRecNO: integer;
i: integer;
Matched: boolean;
begin
try
ADataSet.CheckBrowseMode;
Fields := TList.Create;
ADataSet.GetFieldList(Fields, AFieldNames);
ControlsDisabled := ADataSet.ControlsDisabled;
if not ControlsDisabled then
ADataSet.DisableControls;

Index := ADataSet.fieldbyname(TField(Fields[0]).FieldName).Index;
if VarIsArray(vals) then
val := vals[0]
else
val := vals;
ADataSet.First;
top := ADataSet.RecNo;
ADataSet.Last;
bottom := ADataSet.RecNo;
FInd := false;
while top <= bottom do
begin
ccc := (top + bottom) div 2;
ADataSet.RecNo := ccc;
if IsAsc then
begin
if ADataSet.Fields[Index].AsVariant > val then
begin
Bottom := ccc - 1;
end
else
if ADataSet.Fields[Index].AsVariant < val then
begin
Top := ccc + 1;
end
else
begin
while (ADataSet.Fields[Index].AsVariant = val) and (not ADataSet.Bof) do
ADataSet.Prior;
if (ADataSet.Bof) and (ADataSet.Fields[Index].AsVariant = val) then
else
ADataSet.Next;
if Fields.Count > 1 then
begin
Matched := false;
while (not Matched) and (ADataSet.Fields[Index].AsVariant = val) and (not ADataSet.Eof) do
begin
Matched := true;
for i := 1 to Fields.Count - 1 do
begin
if TField(Fields[i]).AsVariant <> vals[i] then
begin
Matched := false;
break;
end;
end;
if Matched then
begin
Find := true;
goto JumpoutMainLoop;
end
else
ADataSet.Next;
end;
end;
if Fields.Count = 1 then
begin
Find := true;
break;
end
else
begin
Find := false;
break;
end;

end;
end
else
begin
if ADataSet.Fields[Index].AsVariant < val then
begin
Bottom := ccc - 1;
end
else
if ADataSet.Fields[Index].AsVariant > val then
begin
Top := ccc + 1;
end
else
begin
while (ADataSet.Fields[Index].AsVariant = val) and (not ADataSet.Bof) do
ADataSet.Prior;
if (ADataSet.Bof) and (ADataSet.Fields[Index].AsVariant = val) then
else
ADataSet.Next;
if Fields.Count > 1 then
begin
Matched := false;
while (not Matched) and (ADataSet.Fields[Index].AsVariant = val) and (not ADataSet.Eof) do
begin
Matched := true;
for i := 1 to Fields.Count - 1 do
begin
if TField(Fields[i]).AsVariant <> vals[i] then
begin
Matched := false;
break;
end;
end;
if Matched then
begin
Find := true;
goto JumpoutMainLoop;
end
else
ADataSet.Next;
end;
end;
if Fields.Count = 1 then
begin
Find := true;
break;
end
else
begin
Find := false;
break;
end;

end;
end;
continue;
JumpoutMainLoop:
break;
end;
finally
if not ControlsDisabled then
ADataSet.EnableControls;
Fields.Free;
end;
result := Find;
end;
...全文
77 1 打赏 收藏 转发到动态 举报
写回复
用AI写文章
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
advancejar 2005-10-10
  • 打赏
  • 举报
回复

2,496

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 数据库相关
社区管理员
  • 数据库相关社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧