unit uSortStringList_TPS_ChunkUploader;
{<Sorts One String List and Regroups another one }

interface

uses
  System.SysUtils, System.Classes,Contnrs;

type
  TSortStringList = class(TDataModule)
  private


  public

class  procedure SortOneOrderManyStringLists(SLToSort: TStringList;
       SLToChangeOrderObjectList: TObjectList; DataType: string;
       IsAscending: boolean);
{< Sorts One and change order in other String Lists that are in ObjectList
So, first of all - ObjectList should be created in that way

String List that should be Sorted should not be in this ObjectList
}

  end;

//var
//  SortStringList: TSortStringList;

implementation

{%CLASSGROUP 'Vcl.Controls.TControl'}

{$R *.dfm}


//-------------------Компараторы----------------------------

function CompareStringAscending(List: TStringList; Index1, Index2: Integer):
Integer;
begin
   Result := CompareText(List[Index1], List[Index2]);
end;


function CompareStringDescending(List: TStringList; Index1, Index2: Integer):
Integer;
begin
   Result := CompareText(List[Index2], List[Index1]);
end;


function CompareIntegersAsc(List: TStringList; Index1, Index2: Integer): Integer;
var
  d1, d2: integer;
begin
  d1 := List[Index1].ToInt64;
  d2 := List[Index2].ToInt64;
  if d1 < d2 then
    Result := -1
  else if d1 > d2 then Result := 1
  else
    Result := 0;
end;


function CompareIntegersDesc(List: TStringList; Index1, Index2: Integer): Integer;
var
  d1, d2: integer;
begin
  d1 := List[Index1].ToInt64;
  d2 := List[Index2].ToInt64;
  if d1 > d2 then
    Result := -1
  else if d1 < d2 then Result := 1
  else
    Result := 0;
end;


function CompareDateTimeAsc(List: TStringList; Index1, Index2: Integer): Integer;
var
  d1, d2: TDateTime;
begin
  d1 := StrToDateTime(List[Index1]);
  d2 := StrToDateTime(List[Index2]);
  if d1 < d2 then
    Result := -1
  else if d1 > d2 then Result := 1
  else
    Result := 0;
end;




function CompareDateTimeDesc(List: TStringList; Index1, Index2: Integer): Integer;
var
  d1, d2: TDateTime;
begin
  d1 := StrToDateTime(List[Index1]);
  d2 := StrToDateTime(List[Index2]);
  if d1 > d2 then
    Result := -1
  else if d1 < d2 then Result := 1
  else
    Result := 0;
end;





//-----------------Основная процедура сортировки------------------


class procedure TSortStringList.SortOneOrderManyStringLists(
  SLToSort:TStringList;
  SLToChangeOrderObjectList:TObjectList;
  DataType:string; // string integer tdatetime
  IsAscending:boolean
  );

var
  SLToSortAdressesBeforeSort: TStringList;
  SLToSortAdressesAfterSort: TStringList;
  BufferSL: TStringList;
  address: longword;
  i: Integer;
  BufferSLObjectList: TObjectList;
  j: Integer;
  NewIndex: Integer;

begin


   //Creation
   BufferSL:=TStringList.Create;
   SLToSortAdressesBeforeSort:=TStringList.Create;
   SLToSortAdressesAfterSort:=TStringList.Create;

   // Adresses before Sort

   for i := 0 to SLToSort.Count-1 do
   begin
   address := longword(Pointer(SLToSort[i]));
   SLToSortAdressesBeforeSort.Add(address.ToString);
   end;



   //Other String Lists Before Sort

   BufferSLObjectList:=TObjectList.Create;

   for i := 0 to SLToChangeOrderObjectList.Count-1 do
   begin
   BufferSLObjectList.Add(TStringList.Create);

   TStringList(BufferSLObjectList.Items[i]).Assign(
   TStringList(SLToChangeOrderObjectList.Items[i]));

   end;


//------------------------------Sorting...


      if AnsiLowerCase(DataType)='string' then

       if IsAscending=true then
      SLToSort.CustomSort(CompareStringAscending) else
      SLToSort.CustomSort(CompareStringDescending);



      if AnsiLowerCase(DataType)='int64' then

       if IsAscending=true then
      SLToSort.CustomSort(CompareIntegersAsc) else
      SLToSort.CustomSort(CompareIntegersDesc);


      if AnsiLowerCase(DataType)='tdatetime' then

       if IsAscending=true then
      SLToSort.CustomSort(CompareDateTimeAsc) else
      SLToSort.CustomSort(CompareDateTimeDesc);



//------------------------------


//-------------Getting Adresses After Sort---------------------

   for i := 0 to SLToSort.Count-1 do
     begin
     address := longword(Pointer(SLToSort[i]));
     SLToSortAdressesAfterSort.Add(address.ToString);
     end;

//-----------------------------------------------------------


//--------------Updating order in other columns---------------------



for j := 0 to BufferSLObjectList.Count-1 do
 begin



   for i := 0 to TStringList(BufferSLObjectList[j]).Count-1 do
     begin
     NewIndex:=SLToSortAdressesAfterSort.IndexOf( SLToSortAdressesBeforeSort[i]);

     if NewIndex<>-1 then
      TStringList(SLToChangeOrderObjectList[j])[NewIndex]:=
       TStringList(BufferSLObjectList[j])[i];// else

      // TStringList(SLToChangeOrderObjectList[j])[NewIndex]:='';


     end;


 end;



//----------------------------------------------------------------





   //Destroying
   FreeAndNil(BufferSL);
   FreeAndNil(BufferSLObjectList);
   FreeAndNil(SLToSortAdressesBeforeSort);
   FreeAndNil(SLToSortAdressesAfterSort);

end;




end.
