I'm trying to sweep the contents of a TFPObjectHashTable according to some filtering condition. Since it can't be iterated in a linear manner (it is a hash table), the only way I've realized so far is the following:
type
TTagCodeHash = class(TFPObjectHashTable)
protected
procedure IsValid(Item: TObject; const Key: string; var Continue: Boolean);
public
procedure Sweep1;
procedure Sweep2;
end;
...
{ TTagCodeHash }
procedure TTagCodeHash.IsValid(Item: TObject; const Key: string;
var Continue: Boolean);
begin
Continue := some_check_for_validity(Item);
end;
procedure TTagCodeHash.Sweep1;
var
Item: THTObjectNode;
begin
repeat
Item := ForEachCall(IsValid);
if Assigned(Item) then
Delete(Item.Key);
until not Assigned(Item);
end;
But this will call
ForEachCall() from the beginning each time after item was deleted.
The next thing I have tried was:
procedure TTagCodeHash.Sweep2;
var
I, J: LongWord;
Valid: Boolean;
begin
for I := Pred(HashTableSize) downto 0 do
if Assigned(Chain(I)) then
for J := Pred(Chain(I).Count) downto 0 do
begin
IsValid(THTObjectNode(Chain(I)[J]).Data, '', Valid);
if not Valid then
begin
{$IF 0}
Chain(I).Delete(J);
Dec(FCount); // <-- Can't access private member FCount
{$ELSE}
Delete(THTObjectNode(Chain(I)[J]).Key);
{$ENDIF}
end;
end;
end;
But the
Count property is read-only and
FCount is private, so the only way to decrement is to call
Delete().
Both
ForEachCall() and
Delete() will start again from the beginning of the table/chain, which is not the most efficient way for filtering.
Does anyone have a better idea how to filter the hash table more efficiently?