Delphi 10.4 动态记录数组的双条件排序实现需求
Delphi 10.4 实现主列+Name列的双条件排序
背景说明
使用Delphi 10.4开发程序,已将数据库多表数据读取到动态记录数组中,初始加载通过SQL按Name字段排序,数据展示在ListView控件中,当前已实现点击列标题按对应列排序的功能,代码运行正常。部分客户存在多个账户,需求为:按指定列(如Renewed)排序时,同分组下的记录需按Name字段有序排列,即实现指定列为主排序条件、Name列为次排序条件的双条件排序。
现有代码定义
记录类型TDDNS
type TDDNS = record ID : Integer; //数据库中的ID Name : String; //客户名称 Alias : string; //客户别名 Domain : string; //DDNS地址 Login : String; //DDNS登录用户名 Password: string; //DDNS登录密码 Renewed: TDate; //DDNS账户续费日期 IsActive: Boolean; //账户是否激活 end;
动态数组定义
DDNSDetails : array of TDDNS;
当前排序相关代码
procedure lvDDNSColumnClick(Sender: TObject; Column: TListColumn); begin SortList(Column.Index); ReloadLV(); end; procedure SortList(Col : Integer); var i, j : Integer; begin if Length(DDNSDetails) > 0 then begin for i := 0 to Length(DDNSDetails)-1 do begin for j := i+1 to Length(DDNSDetails)-1 do begin if Col = 0 then //Name列 begin if UpperCase(DDNSDetails[i].Name) > UpperCase(DDNSDetails[j].Name) then SwapRecord(i, j); end else if Col = 1 then //Alias列 begin if UpperCase(DDNSDetails[i].Alias) > UpperCase(DDNSDetails[j].Alias) then SwapRecord(i, j); end else if Col = 2 then //Domain列 begin if UpperCase(DDNSDetails[i].Domain) > UpperCase(DDNSDetails[j].Domain) then SwapRecord(i, j); end else if (Col = 3) then //Renewed列 begin if DDNSDetails[i].Renewed > DDNSDetails[j].Renewed then SwapRecord(i, j); end else if Col = 4 then //IsActive列 begin // 布尔值排序:激活的在前或在后可根据需求调整 if DDNSDetails[i].IsActive < DDNSDetails[j].IsActive then SwapRecord(i, j); end; end; end; // 重置列标题标记 lvDDNS.Columns[0].Caption := 'Client Name'; lvDDNS.Columns[1].Caption := 'Trading As'; lvDDNS.Columns[2].Caption := 'Domain Address'; lvDDNS.Columns[3].Caption := 'Renewed'; lvDDNS.Columns[4].Caption := 'Active'; lvDDNS.Columns[Col].Caption := '|| '+lvDDNS.Columns[Col].Caption+' ||'; end; end; procedure SwapRecord(var i, j : Integer); var temp : TDDNS; begin temp := DDNSDetails[i]; DDNSDetails[i] := DDNSDetails[j]; DDNSDetails[j] := temp; end;
问题分析
当前排序逻辑仅针对点击的列做单条件排序,当主列值相同时(如多个账户的续费日期相同),不会再按Name字段排序,导致同组记录无序。
解决方案:修改SortList实现双条件排序
在每个主列的排序判断中,增加主列值相等时按Name字段排序的逻辑,以下是修改后的SortList代码:
procedure SortList(Col : Integer); var i, j : Integer; begin if Length(DDNSDetails) > 0 then begin for i := 0 to Length(DDNSDetails)-1 do begin for j := i+1 to Length(DDNSDetails)-1 do begin if Col = 0 then //Name列作为主列时,直接按Name排序 begin if UpperCase(DDNSDetails[i].Name) > UpperCase(DDNSDetails[j].Name) then SwapRecord(i, j); end else if Col = 1 then //Alias为主列,Name为次列 begin if UpperCase(DDNSDetails[i].Alias) > UpperCase(DDNSDetails[j].Alias) then SwapRecord(i, j) else if UpperCase(DDNSDetails[i].Alias) = UpperCase(DDNSDetails[j].Alias) then begin // Alias相同时按Name排序 if UpperCase(DDNSDetails[i].Name) > UpperCase(DDNSDetails[j].Name) then SwapRecord(i, j); end; end else if Col = 2 then //Domain为主列,Name为次列 begin if UpperCase(DDNSDetails[i].Domain) > UpperCase(DDNSDetails[j].Domain) then SwapRecord(i, j) else if UpperCase(DDNSDetails[i].Domain) = UpperCase(DDNSDetails[j].Domain) then begin // Domain相同时按Name排序 if UpperCase(DDNSDetails[i].Name) > UpperCase(DDNSDetails[j].Name) then SwapRecord(i, j); end; end else if Col = 3 then //Renewed为主列,Name为次列 begin if DDNSDetails[i].Renewed > DDNSDetails[j].Renewed then SwapRecord(i, j) else if DDNSDetails[i].Renewed = DDNSDetails[j].Renewed then begin // 续费日期相同时按Name排序 if UpperCase(DDNSDetails[i].Name) > UpperCase(DDNSDetails[j].Name) then SwapRecord(i, j); end; end else if Col = 4 then //IsActive为主列,Name为次列 begin // 布尔值排序:激活状态相同则按Name排序 if DDNSDetails[i].IsActive < DDNSDetails[j].IsActive then SwapRecord(i, j) else if DDNSDetails[i].IsActive = DDNSDetails[j].IsActive then begin if UpperCase(DDNSDetails[i].Name) > UpperCase(DDNSDetails[j].Name) then SwapRecord(i, j); end; end; end; end; // 重置列标题标记 lvDDNS.Columns[0].Caption := 'Client Name'; lvDDNS.Columns[1].Caption := 'Trading As'; lvDDNS.Columns[2].Caption := 'Domain Address'; lvDDNS.Columns[3].Caption := 'Renewed'; lvDDNS.Columns[4].Caption := 'Active'; lvDDNS.Columns[Col].Caption := '|| '+lvDDNS.Columns[Col].Caption+' ||'; end; end;
说明
- 当点击某列作为主排序条件时,若该列值相同,自动按
Name字段(不区分大小写)进行二次排序; - 布尔列(IsActive)的排序逻辑可根据需求调整,示例中设置为激活的记录在前;
- 保持原有的
SwapRecord过程和列点击事件逻辑不变,仅修改SortList的判断逻辑即可实现需求。
内容的提问来源于stack exchange,提问作者WackyWabbit
相关产品推荐
相关产品推荐

