Delphi: 存储TObjectList的多个排序

Delphi: Store multiple Sortings of TObjectList

我有一堆存储在 TObjectList 中的 TCoordinates。为了更快地找到坐标,必须对列表进行排序。问题是我交替搜索 x 和 y。有没有内置的方法来存储排序的结果,所以我不需要一次又一次地对列表进行排序。

unit uWhosebugQuestion;

interface

uses
  System.Generics.Collections, System.Generics.defaults;

type
  TCoordinate = class(Tobject)
    public
      x: Integer;
      y: Integer;
  end;

  TMultipleSortedList = class(TObjectlist<TCoordinate>)
    public
      // StoredSortingByX: List;
      // StoredSortingByY: List;
      procedure SortAndStoreByX;
      procedure SortAndStoreByY;
  end;

implementation

procedure TMultipleSortedList.SortAndStoreByX;
begin
  // TODO -cMM: TMultipleSortedList.SortAndStoreByX default body inserted
end;

procedure TMultipleSortedList.SortAndStoreByY;
begin
  // TODO -cMM: TMultipleSortedList.SortAndStoreByY default body inserted
end;

end.

创建一个索引图来表示两个不同的订单。这只是一个动态整数数组。

type
  TListOrder = TArray<Integer>;

当您希望使用该顺序阅读某项内容时,您可以这样做:

function GetItem(Index: Integer; const Order: TListOrder): TItem;
begin
  Result := List[Order[Index]];
end;

这里的关键点是我们永远不会修改 List 的内容。我们认为这是无序的。相反,我们将订单与容器分开。这允许我们有多个这样的订单。

下一个问题是如何创建订单。首先用所有有效索引填充订单:

var
  i: Integer;
  Order: TListOrder;
....
SetLength(Order, List.Count);
for i := 0 to List.Count-1 do
  Order[i] := i;

现在您可以这样排序:

TArray.Sort<Integer>(Order, Comparer);

最后,用什么作为比较器。这就是魔法发生的地方。

var
  Comparer: IComparer<Integer>;
....
Comparer := 
  function(const Left, Right: Integer): Integer
  var
    LeftItem, RightItem: TItem;
  begin
    LeftItem := GetItem(Left, Order);
    RightItem := GetItem(Right, Order);
    Result := ...; // your compare logic goes here
  end;

就是这样。

如果列表中的对象没有改变,您可以使用 TList<> 来存储对对象的附加引用,而不是 David Heffernan 建议的整数数组。它在访问时间上有一个小优势。