0

我想TObjectList<T>使用我自己的比较器函数对下面显示的比较器函数代码进行排序。

我希望我的 ObjectList 能够在升序和降序两个方向上进行排序以实现这一点,我使用具有两个参数 S1 和 S2 的 SysUtil.CompareText 并以降序方式排序,我正好与 CompareText 结果的符号相反。我不知道是否存在另一种解决方案,如果 s1 大于 S2 则一切都很好,反之亦然,但是如果 s1 = s2 在正常情况下,列表中没有重新索引,因为列中的所有元素都是相同的,但是相反的发生 TObjectList 排序列表好像 s1 > s2 或 s1 < s2..

我的问题是如何实现支持平等和差异的比较器?

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;
4

1 回答 1

3

如果 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;

比较是一种数学,一种代数。你证明了一些公理,然后一些理论开始起作用。但仅在公理证明之后,不超过实际定理项。

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

尝试阅读http://www.howzatt.demon.co.uk/articles/2011-05-equality.html

于 2013-02-26T21:00:20.243 回答