Delphi: keeping multiple TObjectList sorts

I have a group of TCoordinates that are stored in TObjectList. To find the coordinate faster, the list must be sorted. The problem is iam alternates with finding x and y. Is there a built-in way to store the sort results so I don't have to sort the list over and over.

unit uStackoverflowQuestion;

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.

      

+3


source to share


2 answers


Create an index map to represent two different orders. It's just a dynamic array of integers.

type
  TListOrder = TArray<Integer>;

      

If you want to read an element using this order, follow these steps:

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

      

The key point here is that we never change the content List

. We think this is disordered. Instead, we keep the order separate from the container. This allows us to have several such orders.

The next question is how to create an order. First of all, write down the order with all valid indices:



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

      

You can now arrange the order:

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

      

Finally, what to use as a comparator. This is where the magic happens.

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;

      

What is it.

+5


source


If the objects in your list do not change, you can use TList <> to store an additional object reference instead of the integer array suggested by David Heffernan. It has a slight advantage in access time.



0


source







All Articles