You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 17:06:30