我在Win 64 sp2上运行D7企业版。
在我的程序中,我有两个列表框(lb1,Lb2)。
Lb1最多可包含35.000个项目。(string4 ) Lb2最多可包含35.000个项目。(string4 )
这两个列表框都已排序。
在列表框中可能有重复的项(从0到30.000 ),我想找到这些重复项。
我已经尝试了“自下而上”类型(例如:从listbox2的底部获取元素,扫描listbox1到底部,标记相等的元素,(最终复制到第三个列表框),再次获取下一个元素I listbox2 do sacn I lisbox1,并继续到顶部f Listbox2。)
这种方法确实有效,但它很繁琐,而且非常慢(大约需要。8分钟(+/-) / 35000个项目LB1 / 25000个项目LB2)。
我想知道是否可以将TStringList组件: TStringList.NoDuplicates;修改为
TStringList.getDuplicates;或者类似的东西,如果有,我该怎么做??
或者我没有在TStringList组件中发现一个“隐藏的”可能性/方法(至少对我来说是这样)?
还是有第三种方法可以找到副本?
请帮帮忙。
谢谢
克里斯
发布于 2020-09-27 20:39:50
这是一个好主意,就像你亲手做的那样,用你的手指沿着每个列表往下看。
以下是完成此操作的过程。
procedure TFormTest.CompareLists(const Lista, Listb, Listc: TStrings);
var
a, b, amax, bmax : integer;
begin
aMax := Lista.Count;
bMax := Listb.Count;
Listc.Clear;
a:=0;
b:=0;
while (a< aMax) and (b<bMax) do
begin
// Once either index goes past end of list we are done;
case Sign( CompareStr( Lista[a], Listb[b])) of // oer CompareText if not case sensitive
-1:
begin
// ista[a] < List0[ b ]b
inc( a );
end;
0:
begin
// a = b
Listc.add( Lista[a] ); // same so could be either
inc(a);
inc(b);
end;
1:
begin
inc( b );
end;
end;
end;
end;你可以直接把它复制到你的程序中。
它还可以很容易地比较复制到外部列表是否值得。我这样做了,发现使用列表框条目大约需要4秒,对于35000个条目(比4个字符长得多),对于单独的列表,使用列表框条目需要不到1秒。这种差异远远超过了将项目复制到单独的字符串列表所需的时间,但这两种时间都比您所实现的要好得多。
下面是完整的测试单元:
unit UnitTest;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, System.Math, Vcl.StdCtrls;
type
TFormTest = class(TForm)
ListBox1: TListBox;
ListBox2: TListBox;
ListBox3: TListBox;
EditCompareLists: TEdit;
EditCompareListBoxes: TEdit;
ButtonTest: TButton;
EditCount1: TEdit;
EditCount2: TEdit;
EditCount3: TEdit;
procedure ButtonTestClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
procedure CompareLists( const Lista, Listb, Listc : TStrings );
end;
var
FormTest: TFormTest;
implementation
{$R *.dfm}
{ TForm1 }
procedure TFormTest.ButtonTestClick(Sender: TObject);
var
List1, List2, List3 : TStringList;
iTime : TTime;
i: Integer;
begin
// 1. Generate lists - should be string[4] but if bigger should slow things down
List1 := TStringList.Create;
Try
List2 := TStringList.Create;
try
List3 := TStringList.Create;
try
List1.Sorted := TRUE;
List2.Sorted := TRUE;
List1.Duplicates := dupIgnore;
List2.Duplicates := dupIgnore;
for i := 1 to 50000 do
begin
List1.Add( IntToStr( Random( 65000 )));
List2.Add( IntToStr( Random( 65000 )));
end;
ListBox1.Items.Assign( List1 );
ListBox2.Items.Assign( List2 );
EditCount1.Text := IntToStr(ListBox1.Items.Count );
EditCount2.Text := IntToStr(ListBox2.Items.Count );
// now see how fast eachcan be sorted
// first - list boxes
iTime := Now;
CompareLists( ListBox1.Items, ListBox2.Items, ListBox3.Items );
iTime := Now - iTime;
EditCompareListBoxes.Text := TimeToStr( iTime );
EditCount3.Text := IntToStr(ListBox3.Items.Count );
// and Lists
iTime := Now;
CompareLists( List1, List2, List3 );
iTime := Now - iTime;
EditCompareLists.Text := TimeToStr( iTime );
finally
List3.Free;
end;
finally
List2.Free;
end;
Finally
List1.Free;
End;
end;
procedure TFormTest.CompareLists(const Lista, Listb, Listc: TStrings);
var
a, b, amax, bmax : integer;
begin
aMax := Lista.Count;
bMax := Listb.Count;
Listc.Clear;
a:=0;
b:=0;
while (a< aMax) and (b<bMax) do
begin
// Once either index goes past end of list we are done;
case Sign( CompareStr( Lista[a], Listb[b])) of // oer CompareText if not case sensitive
-1:
begin
// ista[a] < List0[ b ]b
inc( a );
end;
0:
begin
// a = b
Listc.add( Lista[a] ); // same so could be either
inc(a);
inc(b);
end;
1:
begin
inc( b );
end;
end;
end;
end;
end.发布于 2020-09-27 17:18:06
要比较两个排序的列表,您可以比较第一个条目,然后根据比较结果前进一个或两个列表:
正如其他人提到的,在列表控件中比较数据将比在字符串列表或数组之间慢得多。
https://stackoverflow.com/questions/64080775
复制相似问题