如何使用注释对字符串列表进行排序
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;
我有带注释的字符串列表(如 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;