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 define
s and include
s. 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!
精彩评论