我需要存储未知数量的组.每个组都有未知数量的元素/项目.这是我的'小组':
TGroup= array of Integer; <------ dynamic array (as you can see) :)
Run Code Online (Sandbox Code Playgroud)
我想用TList来保持我的团队.我的想法是,我可能希望稍后访问这些组并向其添加更多项目.
我有这个代码,但我不能让它工作:
TYPE
TGroup= array of Integer; // Each group has x items (x can be from 1 to 10000)
procedure TForm1.FormCreate(Sender: TObject);
VAR CurGroup: TGroup;
grp, item: Integer;
Groups: TList; // can contain up to 1 million groups
begin
Groups:= TList.Create;
{ Init }
for grp:= 1 to 4 DO // Put a dummy item in TList
begin
SetLength(CurGroup, 1); // Create new group
Groups.Add(@CurGroup); // Store it
end;
CurGroup:= NIL; // Prepare for next use
for grp:= 1 to 4 DO // We create 4 groups. Each group has 3 items
begin
CurGroup:= Groups[Groups.Count-1]; // We retrieve the current group from list in order to add more items to it
{ We add few items }
for item:= 0 to 2 DO
begin
SetLength(CurGroup, Length(CurGroup)+1); // reserve space for each new item added
CurGroup[item]:= Item;
end;
Groups[Groups.Count-1]:= @CurGroup; // We put the group back into the list
end;
{ Verify }
CurGroup:= NIL;
CurGroup:= Groups[0];
Assert(Length(CurGroup)> 0); // FAIL
if (CurGroup[0]= 0)
AND (CurGroup[1]= 1)
AND (CurGroup[2]= 2)
then Application.ProcessMessages;
FreeAndNil(Groups);
end;
Run Code Online (Sandbox Code Playgroud)
注意:代码已完成.您可以将其粘贴到Delphi(7)中进行试用.
哦,这在新版本的Delphi中会更好......你会使用通用的TList <T>.var组:TList <TGroup>;
你最好的选择是使用另一个动态数组:组:TGroup数组;
原因是动态数组是编译器管理和引用计数.TList仅适用于指针.当试图将dynarrays放入TList时,没有直接的方法来保持引用计数的合理性.
您遇到的另一个问题是您将动态数组变量的堆栈地址添加到TList,而不是实际的数组.@CurGroup表达式是"CurGroup变量的地址",它是一个局部变量,位于堆栈中.
我创建了一个围绕动态数组 RTTI 的包装器。
这只是初稿,但它的灵感来自于你的问题以及TList缺少方法的事实。
type
TGroup: array of integer;
var
Group: TGroup;
GroupA: TDynArray;
i, v: integer;
begin
GroupA.Init(TypeInfo(TGroup),Group); // associate GroupA with Group
for i := 0 to 1000 do begin
v := i+1000; // need argument passed as a const variable
GroupA.Add(v);
end;
v := 1500;
if GroupA.IndexOf(v)<0 then // search by content
ShowMessage('Error: 1500 not found!');
for i := GroupA.Count-1 downto 0 do
if i and 3=0 then
GroupA.Delete(i); // delete integer at index i
end;
Run Code Online (Sandbox Code Playgroud)
该TDynArray包装器也适用于字符串数组或记录数组...记录只需要打包并且只有非引用计数字段(字节、整数、双精度...)或字符串引用计数字段(无变体或接口)之内)。
IndexOf() 方法将按内容搜索。也就是说,例如对于记录数组,所有记录字段(包括字符串)必须匹配。
请参阅TDynArray我们源代码存储库中的SynCommons.pas 单元。适用于 Delphi 6 到 XE,并处理 Unicode 字符串。
该TTestLowLevelCommon._TDynArray方法是与该包装器相关的自动化单一测试。您将在此处找到记录数组示例和更高级的功能。
我目前正在实施SaveToStream和LoadToStream方法......
也许是在所有 Delphi 版本中使用类似通用功能的新方法。
编辑:
我向TDynArray记录/对象添加了一些新方法:
LoadFromStream/SaveToStream或LoadFrom/SaveTo方法) - 它将使用专有但非常快的二进制流布局;CreateOrderedIndex- 在这种情况下,您可以有多个顺序相同的数据);Find方法可以使用快速二分搜索(如果可用)。这些新方法的工作原理如下:
var
Test: RawByteString;
...
Test := GroupA.SaveTo;
GroupA.Clear;
GroupA.LoadFrom(Test);
GroupA.Compare := SortDynArrayInteger;
GroupA.Sort;
for i := 1 to GroupA.Count-1 do
if Group[i]<Group[i-1] then
ShowMessage('Error: unsorted!');
v := 1500;
if GroupA.Find(v)<0 then // fast binary search
ShowMessage('Error: 1500 not found!');
Run Code Online (Sandbox Code Playgroud)
仍然更接近通用范例,速度更快,对于 Delphi 6 到 XE...