Delphi 排序对象列表<;T>;同一比较值集群内的问题

Delphi 排序对象列表<;T>;同一比较值集群内的问题,delphi,generics,sorting,tobjectlist,Delphi,Generics,Sorting,Tobjectlist,我想使用自己的比较器函数对TObjectList进行排序比较器函数代码如下所示 我希望我的ObjectList能够按照两个方向进行升序和降序排序,为了实现这一点,我使用SysUtil.CompareText,它有两个参数S1和S2,并且按照降序排序,我正好与CompareText结果的符号相反。我不知道是否存在另一种解决方案,如果s1大于S2,则一切正常,反之亦然。但是,如果s1=S2,在正常情况下,列表中没有重新索引,因为列中的所有元素都相同,但相反 Occessed TObjectList按

我想使用自己的比较器函数对
TObjectList
进行排序比较器函数代码如下所示

我希望我的ObjectList能够按照两个方向进行升序和降序排序,为了实现这一点,我使用SysUtil.CompareText,它有两个参数S1和S2,并且按照降序排序,我正好与CompareText结果的符号相反。我不知道是否存在另一种解决方案,如果s1大于S2,则一切正常,反之亦然。但是,如果s1=S2,在正常情况下,列表中没有重新索引,因为列中的所有元素都相同,但相反 Occessed TObjectList按s1>s2或s1 我的问题是如何实现支持相等和差异的比较器

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);
  // all ids are identical
end;

procedure TPersons.Sort(Direction: string);
var
  Comparer   : IComparer<TPerson>;
  Comparison : TComparison<TPerson>;
begin
  if Direction = 'Ascending' then

    Comparison := function(const Person1, Person2 : TPerson): Integer
                  begin
                    result := CompareText(Person1.ID, Person2.ID);
                  end;

  if Direction = 'Descending' then

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

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

    inherited Sort(Comparer);
end;
TPerson=class
私有的
FName:字符串;
FId:字符串;
公众的
属性名称:字符串读取FName写入FName;
属性ID:字符串读取FID写入FID;
结束;
TPersons=类(TObjectList)
公众的
构造函数Create();
程序排序(方向:字符串);重新引入;
结束;
程序TForm4.按钮1单击(发件人:ToObject);
变量
人员名单:TPersons;
I:整数;
开始
PersonList:=TPersons.Create;
PersonsList.Sort('升序');
对于I:=0到PersonList。计数-1 do
ShowMessage(PersonsList[i].Name);
结束;
{TPersons}
构造函数TPersons.Create;
变量
个人:TPerson,;
开始
Person:=TPerson.Create;
人名:=‘法蒂赫’;
Person.ID:=“1”;
自我添加(人);
Person:=TPerson.Create;
姓名:=“穆罕默德”;
Person.ID:=“1”;
自我添加(人);
Person:=TPerson.Create;
姓名:=“oussama”;
Person.ID:=“1”;
自我添加(人);
//所有ID都是相同的
结束;
过程TPersons.Sort(方向:字符串);
变量
比较器:IComparer;
比较:t比较;
开始
如果方向=‘上升’,则
比较:=函数(const Person1,Person2:TPerson):整数
开始
结果:=比较文本(Person1.ID,Person2.ID);
结束;
如果方向=‘下降’,则
比较:=函数(const Person1,Person2:TPerson):整数
开始
结果:=-CompareText(Person1.ID,Person2.ID);
结束;
比较器:=TComparer.Construct(比较);
继承排序(比较器);
结束;
如果在正常情况下s1=s2,则列表中没有重新索引,因为列中的所有元素都相同

这是错误的想法。计算机应该按你说的去做,但仅此而已。 如果您告诉计算机这些对象是相等的(换句话说,比较器函数返回零),那么计算机有权将它们按适合其内部排序实现的任何顺序排列

如果您确实希望具有相同ID的对象集群之间有某种特定的顺序,那么这只意味着具有相同ID的对象实际上并不相等,至少不是所有这些对象

当然,如果ID不同,那么对象也会不同。但是,即使这些ID是相同的——只要您关心排序,这就证明了这些对象对您来说仍然不同,并且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;

     ...et cetera
  end;
比较:=函数(const Person1,Person2:TPerson):整数 开始 结果:=比较文本(Person1.ID,Person2.ID); 如果结果为0,则退出; 结果:=CompareText(Person1.Name,Person2.Name); 如果结果为0,则退出; 结果:=人1.年龄-人2.年龄; 如果结果为0,则退出; 结果:=性别比较(Person1.Sex,Person2.Sex); 如果结果为0,则退出; 结果:=人员1.工资-人员2.工资; 如果结果为0,则退出; …等等 结束; 比较是一种数学,一种代数。你证明了一些公理,然后一些理论开始起作用。但只有在公理证明之后,才不超过实际的定理项

您关心具有相同ID的对象的顺序这一事实表明该公理是错误的。比较过程比ID本身更复杂。 您必须制作一个比较器,该比较器只会在真正相等的对象上返回零,换句话说,您不完全关心对象的顺序

试着阅读

如果在正常情况下s1=s2,则列表中没有重新索引,因为列中的所有元素都相同

这是错误的想法。计算机应该按你说的去做,但仅此而已。 如果您告诉计算机这些对象是相等的(换句话说,比较器函数返回零),那么计算机有权将它们按适合其内部排序实现的任何顺序排列

如果您确实希望具有相同ID的对象集群之间有某种特定的顺序,那么这只意味着具有相同ID的对象实际上并不相等,至少不是所有这些对象

当然,如果ID不同,那么对象也会不同。但是,即使这些ID是相同的——只要您关心排序,这就证明了这些对象对您来说仍然不同,并且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;

     ...et cetera
  end;
比较:=函数(const Person1,Person2:TPerson):整数 开始 结果:=比较文本(Person1.ID,Person2.ID); 如果结果为0,则退出; 结果:=CompareText(Person1.Name,Person2.Name); 如果结果为0,则退出; 结果:=人1.年龄-人2.年龄; 如果结果为0,则退出; 结果:=性别比较(Person1.Sex,Person2.Sex); 如果结果为0,则退出; 结果:=人员1.工资-人员2.工资; 如果结果为0,则退出; …等等 结束; 比较是一种数学,一种代数。你证明了一些公理,然后证明了一些理论