delphi – 如何使一个类似Excel的A排序,然后通过B在TObjectList
我刚刚开始使用泛型,我目前在多个字段上进行排序时遇到问题。
案件: 编辑:必须在运行时更改字段排序顺序。 (即,在一种情况下,用户想要排序顺序A,B,C – 在另一场景中他想要B,A,C – 在另一个A,C,D) 说我们有一个未排序的人员列表: Lastname Age --------------------- Smith 26 Jones 26 Jones 24 Lincoln 34 现在如果我按姓氏排序: Lastname ▲ Age --------------------- Jones 26 Jones 24 Lincoln 34 Smith 26 那么如果我按年龄排序,我想要这样: Lastname ▲ Age ▲ --------------------- Jones 24 Jones 26 Smith 26 Lincoln 34 为了做到这一点,我已经做了两个比较器 – 一个TLastNameComparer和一个TAgeComparer。 我现在打电话 PeopleList.Sort(LastNameComparer) PeopleList.Sort(AgeComparer) 现在我的问题是这不产生我想要的输出,但是 Lastname ? Age ? --------------------- Jones 24 Smith 26 Jones 26 Lincoln 34 史密斯26号出现在琼斯之前,26岁。所以看起来它不保留以前的排序。 我知道我可以做一个比较LastName和Age的比较器,但是问题是,我必须对TPerson中存在的各个字段的每个组合进行比较。 有可能做我想要使用多个TComparers,或者我可以如何完成我想要的? 谢谢… 新年更新 祝你新年快乐。 只是为了参考未来的访客,这是(几乎)我现在使用的代码。 首先,我做了一个基类TSortCriterion和一个TSortCriteriaComparer,以便将来可以在多个类中使用这些。 TSortCriterion<T> = Class(TObject) Ascending: Boolean; Comparer: IComparer<T>; end; TSortCriteriaComparer<T> = Class(TComparer<T>) Private SortCriteria : TObjectList<TSortCriterion<T>>; Public Constructor Create; Destructor Destroy; Override; Function Compare(Const Right,Left : T):Integer; Override; Procedure ClearCriteria; Virtual; Procedure AddCriterion(NewCriterion : TSortCriterion<T>); Virtual; End; implementation { TSortCriteriaComparer<T> } procedure TSortCriteriaComparer<T>.AddCriterion(NewCriterion: TSortCriterion<T>); begin SortCriteria.Add(NewCriterion); end; procedure TSortCriteriaComparer<T>.ClearCriteria; begin SortCriteria.Clear; end; function TSortCriteriaComparer<T>.Compare(Const Right,Left: T): Integer; var Criterion: TSortCriterion<T>; begin for Criterion in SortCriteria do begin Result := Criterion.Comparer.Compare(Right,Left); if not Criterion.Ascending then Result := -Result; if Result <> 0 then Exit; end; end; constructor TSortCriteriaComparer<T>.Create; begin inherited; SortCriteria := TObjectList<TSortCriterion<T>>.Create(True); end; destructor TSortCriteriaComparer<T>.Destroy; begin SortCriteria.Free; inherited; end; 最后,为了使用排序标准: Procedure TForm1.SortList; Var PersonComparer : TSortCriteriaComparer<TPerson>; Criterion : TSortCriterion<TPerson>; Begin PersonComparer := TSortCriteriaComparer<TPerson>.Create; Try Criterion:=TSortCriterion<TPerson>.Create; Criterion.Ascending:=True; Criterion.Comparer:=TPersonAgeComparer.Create PersonComparer.AddCriterion(Criterion); Criterion:=TSortCriterion<TPerson>.Create; Criterion.Ascending:=True; Criterion.Comparer:=TPersonLastNameComparer.Create PersonComparer.AddCriterion(Criterion); PeopleList.Sort(PersonComparer); // Do something with the ordered list of people. Finally PersonComparer.Free; End; End; 解决方法
将排序标准放在包括排序方向和用于比较项目的功能的列表中。这样的记录可以帮助:
type TSortCriterion<T> = record Ascending: Boolean; Comparer: IComparer<T>; end; 当用户配置所需的排序时,使用该记录的实例填充列表。 var SortCriteria: TList<TSortCriterion>; Comparer成员将根据名称和年龄参考您已经编写的用于比较的功能。现在写一个引用该列表的单一比较函数。这样的事情 function Compare(const A,B: TPerson): Integer; var Criterion: TSortCriterion<TPerson>; begin for Criterion in SortCriteria do begin Result := Criterion.Comparer.Compare(A,B); if not Criterion.Ascending then Result := -Result; if Result <> 0 then Exit; end; end; (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |