开发者

Does Delphi 5 have a sorted dictionary container?

I'm new to Delphi 5 and looking for a container (ideally a built-in one) that will do the same job as map does in C++ (i.e. a sorted dictionary). I've done a preliminary Google search but nothing obvious seems to be suggesting开发者_运维百科 itself. Please can anyone point me in the right direction?


Take a look at our TDynArray wrapper.

It's a wrapper around any existing dynamic array (including dynamic array of records), which will add TList-like methods to the dynamic array. With even more features, like search, sorting, hashing, and binary serialization. You can set the array capacity with an external Count variable, so that insertion will be much faster.

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!');

This example uses an array of integer, but you may use it with an array of records, even containing strings, nested dynamic arrays, or other records.

Works from Delphi 5 up to XE.

I find it even easier to use than generics (e.g. for the auto-serialization feature). ;)

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


Well if D5 doesn't contain THashedStringList then maybe this one (from OmniThreadLibrary) does the job:

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

I cite:

Tested with Delphi 2007. Should work with older versions, too.

Well, your version is definitely older :)


This can be accomplished 'out of the box' in D5 using TList.Sort or TObjectList.Sort - in your case you'd probably want to implement a class along the lines of:

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

To store in your list, then implement TList.Sort or TObjectList.Sort using your index value for sorting. It will take a bit of work but not terrible. See the D5 help on these classes for implementation details.

Unfortunately there are no generics in D5 so you'll probably have to to a lot of type casting or develop redundant container classes for different types.


This brings back memories. There is another interesting technique that's suitable for ancient versions of Delphi like yours. Read on!

From your description you sound like you want a fairly generic container - ie, one you can use with a variety of types. This cries out for generics (yes, use a new Delphi!) But back in the old days, there used to be a slightly hacky way to implement templates / generics with Delphi pre-2009, using a series of defines and includes. It took a bit of googling, but here's an article on these 'generics' that's much like what I remember. It's from 2001; in those days Delphi 5 was still recent-ish.

The rough idea is this: write a class to do what you want (here, a map from key to value) for a type, and get it working. Then change that file to use a specific name for the type (TMyType, anything really) and strip the file so it's no longer a valid unit, but contains code only. (I think two partial files, actually: one for the interface section, one for implementation.) Include the contents of the file using {$include ...}, so your whole Pascal file is compiled using your definitions and then the contents of the other partial included files which uses those definitions. Neat, hacky, ugly? I don't know, but it works :)

The example article creates a typed object list (ie, a list not of TObject but TMemo, TButton, etc.) You end up with a file that looks like this (copied from the linked article):

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.

You will need to write your own map-like class, although you should be able to base it on this class. I remember that there used to be a set of 'generic' containers floating around the web which may have used this technique, and I would guess map is among them. I'm afraid I don't know where it is or who it was by, and Googling for this kind of thing shows lots of results for modern versions of Delphi. Writing your own might be best.

Edit: I found the same article (same text & content) but better formatted on the Embarcadero Developer Network site.

Good luck!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜