Один из вариантов заключается в анализе содержимого TStringList
во втором списке, который разделяет и группирует имена, значения и строки комментариев вместе, а затем сортирует t список шляп по именам по мере необходимости, затем повторно заполните 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;
я использовал дженерики, так как я знал, что они были доступны, как вопрос помечен XE8. В любом случае единственными изменениями, которые я предлагаю, является добавление обработки исключений, чтобы обеспечить правильную очистку вещей в случае ошибки и изменить 'Sort()' на 'CustomSort()', чтобы вы могли сортировать только по фактическим именам (как и ОП), а не целыми линиями. Ваш обработчик сортировки может использовать 'TStringList.Names []' для извлечения имен каждой строки. –
Предоставляется в качестве удобства для других. Я согласен, что вам понадобится обычная сортировка, так как числа имеют более низкое порядковое значение, чем =. Нет никаких известных исключений, которые мне нужно обработать, но я сделаю, наконец, бесплатно –
Что касается исключений, я больше думал об ошибках выделения памяти, а не о других ошибках во время выполнения. Вы всегда должны использовать 'try/finally' как минимум при работе с локальными парами' Create/Free'. И не забывайте, что 'TStringList' не владеет указателями' Objects [] ', поэтому вы должны' Free' их вручную, прежде чем освобождать 'TStringList', если вы используете' finally', чтобы освободить его. –