4

我是 Delphi 5 的新手,正在寻找一个容器(最好是内置的),它可以完成与mapC++ 中相同的工作(即排序字典)。我已经进行了初步的谷歌搜索,但似乎没有任何明显的迹象。请问有人能指出我正确的方向吗?

4

4 回答 4

3

看看我们的TDynArray包装。

它是任何现有动态数组(包括动态记录数组)的包装器,它将TList向动态数组添加类似方法。具有更多功能,例如搜索、排序、散列和二进制序列化。您可以使用外部Count变量设置数组容量,这样插入会更快。

type
   TGroup: array of integer;
var
   Group: TGroup;
   GroupA: TDynArray;
   i, v: integer;
   Test: RawByteString;
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
  Test := GroupA.SaveTo; // serialization into Test
  GroupA.Clear;
  GroupA.LoadFrom(Test);
  GroupA.Compare := SortDynArrayInteger;
  GroupA.Sort; // will sort the dynamic array according to the Compare function
  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!');

此示例使用整数数组,但您可以将其与记录数组一起使用,甚至包含字符串、嵌套动态数组或其他记录。

适用于从 Delphi 5 到 XE。

我发现它比泛型更容易使用(例如,对于自动序列化功能)。;)

http://blog.synopse.info/post/2011/03/12/TDynArray-and-Record-compare/load/save-using-fast-RTTI

于 2011-08-12T15:17:18.557 回答
1

这可以使用 TList.Sort 或 TObjectList.Sort 在 D5 中“开箱即用”完成 - 在您的情况下,您可能希望按照以下方式实现一个类:

  TMyClass
   public  
      Index:integer;
      Value:TWhatever;
      ...
   end;

要存储在您的列表中,然后使用您的索引值实现 TList.Sort 或 TObjectList.Sort 进行排序。这将需要一些工作,但并不可怕。有关实现的详细信息,请参阅有关这些类的 D5 帮助。

不幸的是,D5 中没有泛型,因此您可能不得不进行大量类型转换或为不同类型开发冗余容器类。

于 2011-08-13T22:05:23.913 回答
1

好吧,如果 D5 不包含THashedStringList,那么也许这个(来自 OmniThreadLibrary)可以完成这项工作:

https://github.com/gabr42/OmniThreadLibrary/blob/master/src/GpStringHash.pas

我引用:

使用 Delphi 2007 测试。也应该适用于旧版本。

好吧,你的版本肯定是旧的 :)

于 2011-08-12T14:44:18.010 回答
0

这勾起了回忆。还有另一种有趣的技术适用于像您这样的古老版本的 Delphi。继续阅读!

根据您的描述,您听起来像是想要一个相当通用的容器 - 即,您可以使用多种类型的容器。这需要泛型(是的,使用新的 Delphi!)但是在过去,使用一系列s 和s 使用Delphi pre-2009 实现模板/泛型曾经有一种稍微老套的方法。谷歌搜索了一下,但这里有一篇关于这些“泛型”的文章,和我记得的很像。从 2001 年开始;在那些日子里,Delphi 5 仍然是最新的。defineinclude

粗略的想法是这样的:编写一个类来为一个类型做你想做的事情(这里是一个从键到值的映射),并让它工作。然后更改该文件以使用类型的特定名称(TMyType实际上是任何东西)并剥离文件,使其不再是有效单元,而仅包含代码。(我认为实际上是两个部分文件:一个用于该interface部分,一个用于implementation。)使用 包含文件的内容{$include ...},因此您的整个 Pascal 文件是使用您的定义编译的,然后是使用这些定义的其他部分包含文件的内容. 整洁,hacky,丑陋?我不知道,但它有效:)

示例文章创建了一个类型化的对象列表(即,不是TObjectbut TMemoTButton等的列表)您最终会得到一个看起来像这样的文件(从链接的文章中复制):

unit u_MemoList;

interface

uses
  Sysutils,
  Classes,
  Contnrs,
  StdCtrls;

{$define TYPED_OBJECT_LIST_TEMPLATE}
type
  _TYPED_OBJECT_LIST_ITEM_ = TMemo;
{$INCLUDE 't_TypedObjectList.tpl'}

type
  TMemoList = class(_TYPED_OBJECT_LIST_)
  end;

implementation

{$INCLUDE 't_TypedObjectList.tpl'}

end.

您将需要编写自己的类似地图的类,尽管您应该能够以此类为基础。我记得曾经有一组漂浮在网络上的“通用”容器可能使用了这种技术,我猜 map 就是其中之一。恐怕我不知道它在哪里或是谁,谷歌搜索这种东西显示了现代版本的 Delphi 的很多结果。自己写可能是最好的。

编辑:我在 Embarcadero Developer Network 网站上找到了相同的文章(相同的文本和内容),但格式更好。

祝你好运!

于 2011-08-15T01:31:17.073 回答