Delphi TList的动态TList

Delphi TList的动态TList,delphi,delphi-xe2,Delphi,Delphi Xe2,我有一个问题:我可以把列表添加到一个列表中吗?我已经试过了,但主列表总是返回一个列表,不知道我错在哪里了。 结构如下: PCombArray = array of Integer; PStatsRecord = record Comb: PCombArray; Freq: Integer; end; PStatsList = TList<PStatsRecord>; TStatsList = TList<PStatsList>; 毫无

我有一个问题:我可以把列表添加到一个列表中吗?我已经试过了,但主列表总是返回一个列表,不知道我错在哪里了。 结构如下:

  PCombArray = array of Integer;
  PStatsRecord = record
    Comb: PCombArray;
    Freq: Integer;
  end;
  PStatsList = TList<PStatsRecord>;
  TStatsList = TList<PStatsList>;
毫无问题地创造它。用于填充子列表的工作过程;例如,我将此过程称为MakeSubList,并将maked列表分配给mypublist,然后将其添加到主列表:

  MainList := TList<PStatsList>.Create;
  try
    MainList.Clear;    
    for index := 1 to N do // generate N subList
    begin  
      ...
      MySubList := MakeSubList(index); // contain correct sub list, no problem here
      ...
      MainList.Add(MySubList);  // add mysublist to mainlist
    end;
    writeln (mainList.count);  // return 1, and not N-1 sublist
  finally
    MainList.Free;
  end; 
感谢帮助我理解的人,这样我才能解决它。再次感谢。

MainList是PStatsList的列表,因此您当然可以向其中添加PStatsList的实例。如果您不被允许,您的代码将根本无法编译或运行

如果循环运行N次,那么MainList.Add将被调用N次,MainList.Count将被调用N次。因此,如果WriteLnMainList.Count打印1,那么我们只能得出N=1的结论

TList允许重复,因此即使MakeSubList每次返回相同的对象,它仍然可以多次添加到主列表中。

MainList是PStatsList的列表,因此您当然可以向其中添加PStatsList的实例。如果您不被允许,您的代码将根本无法编译或运行

如果循环运行N次,那么MainList.Add将被调用N次,MainList.Count将被调用N次。因此,如果WriteLnMainList.Count打印1,那么我们只能得出N=1的结论


TList允许重复,因此即使MakeSubList每次返回相同的对象,它仍然可以多次添加到主列表中。

make sublist函数可能错误,或者,您可能会对自己的命名约定感到困惑,这些约定根本没有遵循类型的常用Delphi/Pascal命名约定

不过,下面的代码可以工作

请注意,TList是一个对象,因此如果要创建TList列表,请确保使用TObjectList而不是普通TList,除非您喜欢内存泄漏。您的内部列表围绕记录类型,不需要是TObjectList,但如果您将StatsRecord更改为作为TObject类类型的TsStatsData,则还应更改为TObjectList

unit aUnit5;

interface

uses Generics.Collections;

procedure Test;

implementation

type
      CombArray = array of Integer;
      StatsRecord = record
        Comb: CombArray;
        Freq: Integer;
      end;
      TStatsList2 = TList<StatsRecord>;
      TStatsList = TObjectList<TStatsList2>;

var
      MainList: TStatsList;
      MySubList: TStatsList2;
      index:Integer;

procedure Test;
begin

      MainList := TStatsList.Create;
      try
        for index := 1 to 10 do // generate N subList
        begin
          MySubList := TStatsList2.Create;
          MainList.Add(MySubList);  // add mysublist to mainlist
        end;
        finally
        MainList.Free;
      end;
end;


end.

make sub list函数可能有误,或者您可能对自己的命名约定感到困惑,这些命名约定没有以任何方式遵循常用的Delphi/Pascal类型命名约定

不过,下面的代码可以工作

请注意,TList是一个对象,因此如果要创建TList列表,请确保使用TObjectList而不是普通TList,除非您喜欢内存泄漏。您的内部列表围绕记录类型,不需要是TObjectList,但如果您将StatsRecord更改为作为TObject类类型的TsStatsData,则还应更改为TObjectList

unit aUnit5;

interface

uses Generics.Collections;

procedure Test;

implementation

type
      CombArray = array of Integer;
      StatsRecord = record
        Comb: CombArray;
        Freq: Integer;
      end;
      TStatsList2 = TList<StatsRecord>;
      TStatsList = TObjectList<TStatsList2>;

var
      MainList: TStatsList;
      MySubList: TStatsList2;
      index:Integer;

procedure Test;
begin

      MainList := TStatsList.Create;
      try
        for index := 1 to 10 do // generate N subList
        begin
          MySubList := TStatsList2.Create;
          MainList.Add(MySubList);  // add mysublist to mainlist
        end;
        finally
        MainList.Free;
      end;
end;


end.

请不要使用P作为非指针类型的前缀。其他人读起来都很困惑。对任何结构化类型(包括数组、类和记录)使用T。为什么不使用MainList:=TStatsList.Create?您将泛型、记录和动态数组混合在一起,效果不是很好。我将尝试展示一个更简单的方法。你能解释一下被接受的答案是如何帮助你解决问题中描述的问题的吗?记住,您描述的问题是打印出来的值不是您期望的值。你好,Rob,我发现了我的错误,正在重写代码。我接受了这个答案,因为我喜欢沃伦P的建议,这帮助我更多地了解了这个名单。从这个意义上说,我接受了这个答案。当然,我也非常感谢你的建议和其他建议,我将在将来加以应用。非常感谢。请不要使用P作为非指针类型的前缀。其他人读起来都很困惑。对任何结构化类型(包括数组、类和记录)使用T。为什么不使用MainList:=TStatsList.Create?您将泛型、记录和动态数组混合在一起,效果不是很好。我将尝试展示一个更简单的方法。你能解释一下被接受的答案是如何帮助你解决问题中描述的问题的吗?记住,您描述的问题是打印出来的值不是您期望的值。你好,Rob,我发现了我的错误,正在重写代码。我接受了这个答案,因为我喜欢沃伦P的建议,这帮助我更多地了解了这个名单。从这个意义上说,我接受了这个答案。当然,我也非常感谢你的建议和其他建议,我将在将来加以应用。非常感谢。即使MyPublist为零,它仍然会被添加。为什么不构建它,@Warren?我的意思是,除了缺少函数和变量的定义。除了省略号之外,我们可以在不改变任何已知内容的情况下填充缺少的部分,代码应该构建。是的,你是对的,它应该构建。我被MainList定义为TStatsList弄糊涂了,这意味着我希望他在定义类型别名后使用它,但他没有,这只是一种糟糕的风格。即使mypublist为零,它仍然会被添加。为什么不构建它,@Warren?我的意思是,除了缺少对
函数和变量。除了省略号之外,我们可以在不改变任何已知内容的情况下填充缺少的部分,代码应该构建。是的,你是对的,它应该构建。我对MainList作为TStatsList的定义感到困惑,这意味着我希望他在定义它之后使用类型别名,但他没有,这只是一种糟糕的风格。我认为困惑是一个比糟糕更好的选择:-我想我认为混淆名称是一个糟糕的选择。您好,我已经查看了您的示例并尝试了它。但现在我有一个问题:在mypublist中[n]应该是mypublist[n-1]的副本,在mypublist[n]中我可以添加元素。然后在myList中,mypublist的容器应该及时更新所有mypublist。例如:mypublist[0]=0;mypublist[1]=0,1;mypublist[2]=0,1,2等,然后mainlist[0]=0;主列表[1]=0,1;mainlist[2]=0,1,2等。在本例中,我假设了整数,但将示例查找到0,1,2等的位置,我们发现了StatsRecord类型。如果你能再帮我一次,谢谢。我不知道你在说什么。你想让MainList[X]成为MainList的第一个X+1元素吗?我认为混淆是一个比糟糕更好的选择:-我想我认为混淆名称是一个糟糕的选择。你好,我已经看过你的示例并尝试过了。但现在我有一个问题:在mypublist中[n]应该是mypublist[n-1]的副本,在mypublist[n]中我可以添加元素。然后在myList中,mypublist的容器应该及时更新所有mypublist。例如:mypublist[0]=0;mypublist[1]=0,1;mypublist[2]=0,1,2等,然后mainlist[0]=0;主列表[1]=0,1;mainlist[2]=0,1,2等。在本例中,我假设了整数,但将示例查找到0,1,2等的位置,我们发现了StatsRecord类型。如果你能再帮我一次,谢谢。我不知道你在说什么。是否希望MainList[X]成为MainList的第一个X+1元素? .. implementation type S64 = string[64]; art_ptr = ^art_rec; art_rec = record sDes: S64; rCost: real; iQty: integer; end; art_file = file of art_rec; var lCatalog: TList; procedure disp_all; var lArt: TList; pA: art_ptr; c, a: integer; begin for c:= 0 to lCatalog.Count -1 do begin lArt:= lCatalog[c]; for a:= 0 to lArt.Count -1 do begin pA:= lArt[a]; Dispose(pA); end; lArt.Clear; lArt.Free; end; lCatalog.Clear; end;// disp_all procedure TfrmMain.FormCreate(Sender: TObject); begin lCatalog:= TList.Create; end;// FormCreate procedure TfrmMain.FormDestroy(Sender: TObject); begin disp_all; lCatalog.Free; end;// FormDestroy // a normal BitButton click that adds 3 records to each art list (2) procedure TfrmMain.bbMCreate_Click(Sender: TObject); const nArt = 2; nRec = 3; var pA: art_ptr; lArt: TList; c: integer; begin // clears any previous added pointer record to art list that was added to the catalog disp_all; // creates art lists and add 'em to the catalog list for c:= 0 to nArt -1 do begin lArt:= TList.Create; lCatalog.Add(lArt); // creates records and add 'em to the art list for a:= 0 to nArt -1 do begin pA:= New(art_ptr); with pA^ do begin sDes:= Format('cat%d-art%d', [c, a]); rCost:= (c+1) * (a +1) *1.0; iQty:= (c+1) *10 + (a +1); end; lArt.Add(pA); end; end; end;// bbMCreate_Click // a normal BitButton click that reads 1 record from 1 art list procedure TfrmMain.bbMRead_Click(Sender: TObject); const c = 1; a = 2; var pA: art_ptr; lArt: TList; begin // gets art list #2 from catalog (index is 0 based. c=1) lArt:= lCatalog[c]; // gets record #3 from art list (index is 0 based. a=2) pA:= lArt[a]; // displays the record in a string grid called sgArt... at row a+1 with sgArt, pA^ do begin // col 0 contains cat index and art index, can be useful... cells[0,a+1]:= Format('\%d\%d', [c,a]); cells[1,a+1]:= sDes; cells[2,a+1]:= FormatFloat('0.00', rCost); cells[3,a+1]:= IntToStr(iQty); end; end;// bbMRead_Click