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 建议的整数数组。它在访问时间上有一个小优势。
我有一堆存储在 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 建议的整数数组。它在访问时间上有一个小优势。