order List with criteria choose to runtime

纵然是瞬间 提交于 2019-12-11 05:57:49

问题


if i have a generics list with more field for example:

PMyList = record 
  Field1, Field2, ... FieldN : Integer;
end;
TMyList = List<PMyList>;

For order the list with criteria choose to runtime (for example: field2 then field2, or: field3 then field1 then field2 etc) there is some solution or i need to do a compare construct for all combination possibile of order that i want?

Mine idea was, if record is N field, i have thinked to a array so defined:

MyArray = array [1..n] of Integer;

and assign a progressive value to elements of array that determine criteria of sord for example if MyArray is as:

MyArray = (5, 1, 3, 4, 2)

mean that my list need to be sort first for field5, then for field1, then for field3, then for field4, then for field2. Mine question then is: can i to do it using one only construct compare for my list?

Thanks very much for help.


回答1:


I'm going to base the notation on your previous question. I'm also going to rename MyArray as FieldPriority.

So, FieldPriority[1] identifies the primary comparison field, FieldPriority[2] identifies the secondary comparison field and so on.

With this in place your compare function looks like this:

type
  TMyRecord  = record
    Value: array [1..5] of Integer;
  end;

function Compare(const Left, Right: TMyRecord): Integer;
var
  i, Field: Integer;
begin
  for i := 1 to 5 do
  begin
    Field := FieldPriority[i];
    Result := CompareInt(Left.Value[Field], Right.Value[Field]);
    if Result<>0 then
      exit;
  end;
end;

It all works much better if the integers in your record are declared as an array rather than individually. That allows you to index them as I do here.

Naturally this could all be generalised to handle arbitrary sized arrays.




回答2:


If I understand you right:

Comparer := TComparer<PMyList>.Construct(
     function(const Left, Right: PMyList): Integer
     var LV, RV, x: Integer;
     begin
        for x := Low(MyArray) to High(MyArray) do begin
           case MyArray[x] of
             1: begin
                LV := Left.Field1;
                RV := Right.Field1;
             end;
             2: begin
                LV := Left.Field2;
                RV := Right.Field2;
             end;
             ...
             else raise Exception.Create('Unhandled fileld index: '+IntToStr(MyArray[x]));
           end;
           Result := LV - RV;
           if(Result <> 0)then Break;
        end;
     end);



回答3:


A method to take field priorities into account:

OverallCompareResult := Sum(CompareResult[i] * (1 shl Priority[i]))

(1 shl Priority[i] = 2 ^ Priority[i])

Priority[] for your example: (4, 1, 3, 2, 5)

CompareResult must be in (-1, 0, 1)



来源:https://stackoverflow.com/questions/8376182/order-list-with-criteria-choose-to-runtime

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!