Delphi中TObjectList<T>多条件排序结果不符合预期如何解决
问题原因分析
你的代码存在3处核心错误,共同导致排序结果不符合预期:
- 1. 排序时机错误
你在列表还没有添加任何元素的时候就执行了Sort方法,后续添加完所有人员数据后没有重新触发排序,当前列表的顺序完全是你调用Add方法的顺序,和排序逻辑无关。 - 2. 单字段比较器返回值逻辑颠倒
Delphi的IComparer<T>.Compare方法有明确约定:- 当
Left参数值 >Right参数值时,返回正数 - 当
Left参数值 <Right参数值时,返回负数 - 二者相等返回0
你写的年龄、姓名比较器逻辑完全反过来了,会直接导致排序方向倒置。
- 当
- 3. 多条件比较器的参数顺序错误
你重写TSortCriteriaComparer<T>.Compare方法时,把参数顺序写成了Right在前、Left在后,和父类的约定不一致,调用子比较器时传参顺序错误,进一步打乱了排序逻辑。
修正方案
1. 修正多条件比较器的参数和调用逻辑
function TSortCriteriaComparer<T>.Compare(const Left, Right: T): Integer; var Criterion: TSortCriterion<T>; begin for Criterion in SortCriteria do begin Result := Criterion.Comparer.Compare(Left, Right); if not Criterion.Ascending then Result := -Result; if Result <> 0 then Exit; end; Result := 0; end;
2. 修正单字段比较器的返回值逻辑
{ TPersonAgeComparer } function TPersonAgeComparer.Compare(const Left, Right: TPerson): Integer; begin // 直接相减即可符合比较器约定,逻辑更简洁 Result := Left.age - Right.age; end; { TPersonLastNameComparer } function TPersonLastNameComparer.Compare(const Left, Right: TPerson): Integer; begin // 调用系统自带的字符串比较函数,避免手动写判断出错 Result := CompareStr(Left.name, Right.name); end;
3. 调整排序时机,所有元素添加完成后再执行排序
begin PersonComparer := TSortCriteriaComparer<TPerson>.Create; try // 排序规则配置代码保持不变,此处省略 PeopleList := TObjectList<TPerson>.Create(True); try // 先添加所有元素 PeopleList.Add(TPerson.Create(26, 'Smith')); PeopleList.Add(TPerson.Create(26, 'Jones')); PeopleList.Add(TPerson.Create(24, 'Jones')); PeopleList.Add(TPerson.Create(34, 'Lincoln')); // 全部添加完成后再执行排序 PeopleList.Sort(PersonComparer); // 输出验证逻辑可选 Writeln('Lastname', #9, 'Age'); Writeln('-------------------'); for Person in PeopleList do Writeln(Person.name, #9, Person.age); finally PeopleList.Free; end; finally PersonComparer.Free; end; Readln; end.
修正后运行即可得到你预期的排序结果。
内容的提问来源于stack exchange,提问作者pio pio
相关产品推荐
相关产品推荐

