1

要約:

TList.IndexOf (ユニット Classes.pas で定義された TList) は、含まれている項目を直線的に反復し、参照を比較します。TList.IndexOf (ユニット Generics.Collections.pas で定義された TList) も、含まれている項目を直線的に反復しますが、比較子を使用して項目が等しいかどうかを比較します。

TList.Sort と TList.Sort の両方で比較子を使用できます。

=================================================

次の単元で定義されている TForceList 型のインスタンスについては、次のように使用できます。

instance.Sort(@ForceCompare);

Value フィールドをソート基準として使用して QuickSort します。しかし、私が電話するとき

instance.IndexOf(AnotherInstance)

その ElementZ フィールドを比較基準、つまり関数として使用したいと考えていForceEqualます。どうすればこれを達成できるのだろうか?

PS: ジェネリック コレクションが使用されている場合は、使用できると思います

TList<TForce>.Create(TComparer<TForce>.Construct(ForceEqual));

ユニット:

    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.
4

3 に答える 3

2

Sort メソッドの背後にある全体的な考え方は、リストを実際に並べ替えるということです。つまり、並べ替えメソッドを呼び出した後、並べ替え基準を満たすようにリスト上の要素の物理的な順序が変更されます。

独自の Delphi RTL コードでわかるように、IndexOf メソッドは参照による線形検索であり、最初に一致した要素の物理インデックスを返します。

返されたインデックスを使用して、次のようにリスト上のオブジェクトを取得できます。

SomeIndex := AList.IndexOf(SomeObject);
//more code...
//you can re-use the reference...
//and maybe more...
SomeObject := AList[SomeIndex];

IndexOf メソッドは、リストの物理的な順序とは異なる基準に基づいてインデックスを返さない理由がわかります...最初に Sort を呼び出すと、物理的な順序は渡された並べ替え基準を反映しています。

そうは言っても、あなたがしたいかもしれないようです

  • 異なる基準でソートされた 2 つの異なるリストを維持し、必要に応じていずれかを使用します。
  • アプリケーションが特定の時点で処理している操作に適用される基準に基づいて、リストを再ソートします。

パフォーマンスの向上は、アプリケーションがこれらのオブジェクトをどのように使用するか、処理するデータの量、さらには実行時にプロセスで使用できるメモリによって異なります。

于 2011-03-10T21:57:22.937 に答える
2

非ジェネリックのTObjectListuses はTList.IndexOf、単純に内部配列を反復処理し、ポインターを比較します。

同様に、ジェネリックは をTObjectList<T>使用しTList<T>.IndexOf、これは を使用しIComparerます。リストの作成時に割り当てられたものを渡すことをTList<T>.Sort使用します。TArray.Sort<T>IComparer

比較子はプライベートであり、リスト コンストラクターでのみ割り当てられるため、この動作をオーバーライドする簡単な方法はわかりません。

アップデート

TList<T>プライベート比較器を変更せずにSort、比較器を引数として受け入れる提供およびオーバーロード。したがって、1 つの比較子を使用して並べ替えることができ、indexof は別のものを使用できます。

于 2011-03-10T21:37:17.503 に答える
1

標準の TObjectList にはありません。これ (実際にはベース TList) は、CustomSort を使用してカスタムの並べ替え関数をサポートするように作成されていますが、カスタムの IndexOf にはそのような規定はありません。もちろん、そのように機能する独自の実装を作成することもできます。

于 2011-03-10T21:25:47.950 に答える