如何使用注释对字符串列表进行排序

How to sort stringlist with comments

我有带注释的字符串列表(如 Ini 文件部分内容):

;comment c
c=str1
;comment b
b=str2
;comment a
a=str3

关于如何按名称对列表进行排序的任何想法:

;comment a
a=str3
;comment b
b=str2
;comment c
c=str1

对的评论在排序时应与对相关联

一个选项是将 TStringList 内容解析为第二个列表,该列表将名称、值和注释字符串分隔并组合在一起,然后根据需要对该列表的名称进行排序,然后重新填充 TStringList 与排序组。例如:

uses
  ...
  System.Classes,
  System.SysUtils,
  System.Generics.Defaults,
  System.Generics.Collections,
  System.StrUtils,
  System.Types;

type
  ItemInfo = record
    LeadingText,
    Name,
    Value: string;
  end;

  ItemInfoComparer = class(TComparer<ItemInfo>)
  public
    function Compare(const Left, Right: ItemInfo): Integer; override;
  end;

function ItemInfoComparer.Compare(const Left, Right: ItemInfo): Integer;
begin
  if (Left.Name <> '') and (Right.Name <> '') then
    Result := AnsiCompareStr(Left.Name, Right.Name)
  else if (Left.Name <> '') then
    Result := -1
  else
    Result := 1;
end;

procedure SortMyList(List: TStringList);
var
  Compare: IComparer<ItemInfo>;
  Items: TList<ItemInfo>;
  Info: ItemInfo;
  I: Integer;
  InText: Boolean;
  S: String;
begin
  Compare := ItemInfoComparer.Create;
  Items := TList<ItemInfo>.Create(Compare);
  try
    Items.Capacity := List.Count;
    InText := False;

    for I := 0 to List.Count-1 do
    begin
      S := Trim(List[i]);
      if (S = '') or (S[1] = ';') then
      begin
        if InText then
          Info.LeadingText := Info.LeadingText + #13 + List[i]
        else
        begin
          Info.LeadingText := List[i];
          InText := True;
        end;
      end else
      begin
        Info.Name := List.Names[I];
        Info.Value := List.ValueFromIndex[I];
        Items.Add(Info);
        Info := Default(ItemInfo);
        InText := False;
      end;
    end;

    if InText then
      Items.Add(Info);

    Items.Sort;

    List.Clear;
    for I := 0 to Items.Count-1 do
    begin
      Info := Items[I];

      if Info.LeadingText <> '' then
      begin
        for S in SplitString(Info.LeadingText, #13) do
          List.Add(S);
      end;

      if Info.Name <> '' then
        List.Add(Info.Name + '=' + Info.Value);
    end;
  finally
    Items.Free;
  end;
end;

这是一个简单的程序,可以将空间作为货物进行分类和处理。我还在文件末尾添加了代码来处理注释。

这将与旧版本的 Delphi 一起工作,这些旧版本没有 Remy 的回答中的泛型或高级类型(为使用旧版本的人提供便利)

function SortKeys(List: TStringList; Index1, Index2: Integer): Integer;
begin
  result := CompareText(List.Names[Index1], List.Names[Index2]);
end;


Procedure SortStringListWithComments(AStrings: TStrings);
var
 LCargoText: TStringList;
 LSortedText : TStringList;
 s: string;
 i : integer;
begin
  LCargoText := nil; 
  LSortedText := TStringList.Create;
  try
    for i := 0 to AStrings.count-1 do
    begin
      s := Trim(AStrings[i]);
      if (s='') or (s[1] = ';') then //LCargoText and blank lines attached to sorted strings (Boolean short circuit assumed here) 
       begin
        if LCargoText = nil then
          LCargoText := TStringList.Create;
        LCargoText.Add(AStrings[i]);
      end
      else
      begin
        LSortedText.AddObject(AStrings[i], LCargoText);
        LCargoText := nil; //set nil to deal with cases where we have no   comments for a following key value pair
      end;

    end;

    LSortedText.CustomSort(SortKeys);

    // LSortedText.sort -  will cause a1=x to be sorted before a=x

    AStrings.clear;

    for i := 0 to LSortedText.count-1 do
    begin
      if  LSortedText.objects[i] <> nil then
      begin
        AStrings.AddStrings(TStringList(LSortedText.Objects[i]));
        LSortedText.Objects[i].Free;
      end;
      AStrings.Add(LSortedText[i]);
    end;

    if LCargoText <> nil then
    begin
      AStrings.AddStrings(LCargoText) ; //comments orphaned at the end of the file
      LCargoText.Free;
    end;
  finally
    LSortedText.Free;
  end; 
end;