Summarization:
TList.IndexOf (TList defined in the unit Classes.pas) iterates linearly through the contained items, and compares the reference. TList.IndexOf (TList defined in the unit Generics.Collections.pas) also iterates linearly through the contained items, but uses a comparer to compare whether the items are equal.
Both TList.Sort and TList.Sort can use a comparer.
=================================================
For an instance of the TForceList type defined in the following unit, I could use
instance.Sort(@ForceCompare);
to QuickSort it using its Value field as sorting criteria. However, when I call
instance.IndexOf(AnotherInstance)
I want to use its ElementZ field as comparing criteria, i.e., the ForceEqual
function. I am wondering how can I achieve this?
PS: If the generics collection is used, I guess I could use
TList<TForce>.Create(TComparer<TForce>.Construct(ForceEqual));
The unit:
unit uChemParserCommonForce;
interface
uses
uMathVector3D,
Contnrs;
type
TForce = class;
TForceList = class;
TForce = class
private
FElementZ: Integer;
FValue: TVector3D;
public
property ElementZ: Integer read FElementZ;
property Value: TVector3D read FValue;
constructor Create(aElementZ: Integer; aX, aY, aZ: Double);
function ToString(): string; {$IF DEFINED(FPC) OR DEFINED(VER210)} override; {$IFEND}
end;
// Mastering Delphi 6 - Chapter 5 -
TForceList = class(TObjectList)
protected
procedure SetObject(Index: Integer; Item: TForce);
function GetObject(Index: Integer): TForce;
public
function Add(Obj: TForce): Integer;
procedure Insert(Index: Integer; Obj: TForce);
property Objects[Index: Integer]: TForce read GetObject
write SetObject; default;
end;
function ForceCompare(Item1, Item2: Pointer): Integer;
function ForceEqual(Item1, Item2: Pointer): Boolean;
implementation
uses
Math, SysUtils;
function ForceCompare(Item1, Item2: Pointer): Integer;
begin
// Ascendent
// Result := CompareValue(TForce(Item1).Value.Len, TForce(Item2).Value.Len);
// Descendent
Result := CompareValue(TForce(Item2).Value.Len, TForce(Item1).Value.Len);
end;
function ForceEqual(Item1, Item2: Pointer): Boolean;
begin
Result := TForce(Item1).ElementZ = TForce(Item2).ElementZ;
end;
constructor TForce.Create(aElementZ: Integer; aX, aY, aZ: Double);
begin
FElementZ := aElementZ;
FValue := TVector3D.Create(aX, aY, aZ);
end;
function TForce.ToString: string;
begin
Result := IntToStr(FElementZ) + ' X: ' + FloatToStr(FValue.X) + ' Y: ' +
FloatToStr(FValue.Y) + ' Z: ' + FloatToStr(FValue.Z);
end;
{ TForceList }
function TForceList.Add(Obj: TForce): Integer;
begin
Result := inherited Add(Obj);
end;
procedure TForceList.SetObject(Index: Integer; Item: TForce);
begin
inherited SetItem(Index, Item);
end;
function TForceList.GetObject(Index: Integer): TForce;
begin
Result := inherited GetItem(Index) as TForce;
end;
procedure TForceList.Insert(Index: Integer; Obj: TForce);
begin
inherited Insert(Index, Obj);
end;
end.
value
field of its TForce objects. However, when searching for the TForce object withElement Z
, I want to simply useElement Z
as the criteria. – RobbIndexOf
method, where there's no criteria involved at all, and take a look at the source code ofSort
method, you'll understand why your requirement does not make sense. – Spitfire