我有带有注释的stringlist(比如Ini文件部分内容):
;comment c
c=str1
;comment b
b=str2
;comment a
a=str3
Run Code Online (Sandbox Code Playgroud)
任何想法如何按名称对此列表进行排序:
;comment a
a=str3
;comment b
b=str2
;comment c
c=str1
Run Code Online (Sandbox Code Playgroud)
对于对的注释应该在排序期间与对链接
一种选择是将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;
Run Code Online (Sandbox Code Playgroud)