Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Сортировка TObjectList по собственной функции сравнения с поддержкой равенства и различия

Delphi , Базы данных , Сортировка и Фильтр

В данной статье мы рассмотрим вопрос сортировки объектов в TObjectList с использованием собственной функции сравнения, которая поддерживает как различия, так и равенство между объектами.

Описание проблемы

Разработчик хочет отсортировать TObjectList с использованием своей функции сравнения. Функция сравнения принимает два параметра (S1 и S2) и использует SysUtil.CompareText для сравнения. Для сортировки в обратном порядке разработчик меняет знак результата функции CompareText. Однако, когда S1 и S2 равны, список не переиндексируется, так как все элементы в столбце идентичны. При сортировке в обратном порядке список сортируется так, как будто S1 > S2 или S1 < S2.

Вопрос

Как реализовать функцию сравнения, которая поддерживает как равенство, так и различия между объектами?

Пример кода

Ниже приведен пример кода, демонстрирующий использование TObjectList и сортировку по собственной функции сравнения:

type
  TPerson = class
  private
    FName: string;
    FId: string;
  public
    property Name: string read FName write FName;
    property ID: string read FID write FID;
  end;

  TPersons = class(TObjectList<TPerson>)
  public
    constructor Create;
    procedure Sort(Direction: string); reintroduce;
  end;

procedure TForm4.Button1Click(Sender: TObject);
var
  PersonsList: TPersons;
  I: Integer;
begin
  PersonsList := TPersons.Create;
  PersonsList.Sort('Ascending');
  for I := 0 to PersonsList.Count - 1 do
    ShowMessage(PersonsList[i].Name);
end;

{ TPersons }

constructor TPersons.Create;
var
  Person: TPerson;
begin
  Person := TPerson.Create;
  Person.Name := 'fateh';
  Person.ID := '1';
  Self.Add(Person);

  Person := TPerson.Create;
  Person.Name := 'mohamed';
  Person.ID := '1';
  Self.Add(Person);

  Person := TPerson.Create;
  Person.Name := 'oussama';
  Person.ID := '1';
  Self.Add(Person);
  // все идентификаторы одинаковы
end;

procedure TPersons.Sort(Direction: string);
var
  Comparer: IComparer<TPerson>;
  Comparison: TComparison<TPerson>;
begin
  if Direction = 'Ascending' then
  begin
    Comparison := function(const Person1, Person2: TPerson): Integer
      begin
        result := CompareText(Person1.ID, Person2.ID);
      end;
  end;

  if Direction = 'Descending' then
  begin
    Comparison := function(const Person1, Person2: TPerson): Integer
      begin
        result := -CompareText(Person1.ID, Person2.ID);
      end;
  end;

  Comparer := TComparer<TPerson>.Construct(Comparison);

  inherited Sort(Comparer);
end;

Подтвержденный ответ

Компаратор должен возвращать нуль только в том случае, когда объекты действительно равны во всех отношениях, о которых заботится разработчик. Если объекты с одинаковыми ID все еще различаются по другим атрибутам, необходимо использовать каскадное сравнение, чтобы определить правильный порядок.

Ниже приведен пример каскадного компаратора, который сравнивает объекты по нескольким атрибутам:

Comparison := function(const Person1, Person2: TPerson): Integer
begin
  Result := CompareText(Person1.ID, Person2.ID);
  if Result <> 0 then
    exit;

  Result := CompareText(Person1.Name, Person2.Name);
  if Result <> 0 then
    exit;

  Result := Person1.Age - Person2.Age;
  if Result <> 0 then
    exit;

  Result := GenderCompare(Person1.Sex, Person2.Sex);
  if Result <> 0 then
    exit;

  Result := Person1.Salary - Person2.Salary;
  if Result <> 0 then
    exit;

  ... и так далее
end;

Альтернативный ответ

Если разработчик все же хочет использовать стандартный интерфейс компаратора и стандартные контейнеры, он не должен делать никаких предположений о свойствах алгоритма сортировки, используемого контейнером. В противном случае, при смене контейнера или алгоритма сортировки поведение программы может измениться.

Заключение

Для правильной сортировки TObjectList по собственной функции сравнения с поддержкой равенства и различия необходимо создать компаратор, который возвращает нуль только в том случае, когда объекты действительно равны во всех отношениях, о которых заботится разработчик. Если объекты с одинаковыми ID все еще различаются по другим атрибутам, необходимо использовать каскадное сравнение, чтобы определить правильный порядок. При использовании стандартных интерфейсов компаратора и контейнеров не следует делать никаких предположений о свойствах алгоритма сортировки, используемого контейнером.

Создано по материалам из источника по ссылке.

В этом тексте рассматривается вопрос сортировки объектов в TObjectList с использованием собственной функции сравнения, которая учитывает как различия, так и равенство между объектами.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: Сортировка и Фильтр ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2025-01-29 02:34:25/0.024924993515015/1