Список заказов с критериями выбора времени выполнения - PullRequest
1 голос
/ 04 декабря 2011

если у меня есть список универсальных элементов с дополнительным полем, например:

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

Для заказа списка с критериями выберите время выполнения (например: field2, затем field2, или: field3, затем field1, затем field2 и т. Д.)есть какое-то решение или мне нужно сделать конструкцию сравнения для всех возможных комбинаций порядка, который я хочу?

Моя идея заключалась в том, что если запись - это поле N, я подумал, что массив определен так:

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

и присваивать прогрессивное значение элементам массива, которые определяют критерии sord, например, если MyArray имеет вид:

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

означает, что мой список должен быть отсортирован сначала для field5, затем дляполе1, затем для поля3, затем для поля4, затем для поля2.Мой вопрос тогда: могу ли я сделать это, используя только одну конструкцию сравнения для моего списка?

Большое спасибо за помощь.

Ответы [ 3 ]

2 голосов
/ 05 декабря 2011

Я собираюсь основать нотацию на вашем предыдущем вопросе .Я также собираюсь переименовать MyArray в FieldPriority.

Итак, FieldPriority[1] идентифицирует первичное поле сравнения, FieldPriority[2] идентифицирует вторичное поле сравнения и т. Д.

Благодаря этому ваша функция сравнения выглядит следующим образом:

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;

Все это работает намного лучше, если целые числа в вашей записи объявлены как массив, а не по отдельности.Это позволяет вам индексировать их, как я делаю здесь.

Естественно, все это можно обобщить для обработки массивов произвольного размера.

2 голосов
/ 04 декабря 2011

Если я вас правильно понял:

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);
0 голосов
/ 04 декабря 2011

Метод для учета приоритетов полей:

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

(1 shl Priority [i]= 2 ^ Приоритет [i])

Приоритет [] для вашего примера: (4, 1, 3, 2, 5)

CompareResult должен быть в (-1, 0, 1)

...