字典不維護元素的順序。它們針對速度進行了優化,而不是保持排序。
如果您需要維護元素的順序,您需要配對列表而不是字典。 Delphi不提供這種開箱即用的功能。您可以使用以下代碼來實現簡單的對列表並根據您的需要對其進行自定義。
type
TPairs<TKey, TValue> = class(TList < TPair < TKey, TValue >>)
protected
fKeyComparer: IComparer<TKey>;
fValueComparer: IComparer<TValue>;
function GetValue(Key: TKey): TValue;
procedure SetValue(Key: TKey; const Value: TValue);
function ComparePair(const Left, Right: TPair<TKey, TValue>): Integer;
public
constructor Create; overload;
procedure Add(const aKey: TKey; const aValue: TValue); overload;
function IndexOfKey(const aKey: TKey): Integer;
function ContainsKey(const aKey: TKey): Boolean; inline;
property Values[Key: TKey]: TValue read GetValue write SetValue;
end;
constructor TPairs<TKey, TValue>.Create;
begin
if fKeyComparer = nil then fKeyComparer := TComparer<TKey>.Default;
if fValueComparer = nil then fValueComparer := TComparer<TValue>.Default;
inherited Create(TDelegatedComparer <TPair<TKey, TValue>>.Create(ComparePair));
end;
function TPairs<TKey, TValue>.ComparePair(const Left, Right: TPair<TKey, TValue>): Integer;
begin
Result := fKeyComparer.Compare(Left.Key, Right.Key);
if Result = 0 then Result := fValueComparer.Compare(Left.Value, Right.Value);
end;
function TPairs<TKey, TValue>.IndexOfKey(const aKey: TKey): Integer;
var
i: Integer;
begin
Result := -1;
for i := 0 to Count - 1 do
if fKeyComparer.Compare(Items[i].Key, aKey) = 0 then
begin
Result := i;
break;
end;
end;
function TPairs<TKey, TValue>.ContainsKey(const aKey: TKey): Boolean;
begin
Result := IndexOfKey(aKey) >= 0;
end;
function TPairs<TKey, TValue>.GetValue(Key: TKey): TValue;
var
i: Integer;
begin
i := IndexOfKey(Key);
if i >= 0 then Result := Items[i].Value
else Result := default (TValue);
end;
procedure TPairs<TKey, TValue>.SetValue(Key: TKey; const Value: TValue);
var
i: Integer;
Pair: TPair<TKey, TValue>;
begin
i := IndexOfKey(Key);
if i >= 0 then FItems[i].Value := Value
else
begin
Pair.Create(Key, Value);
inherited Add(Pair);
end;
end;
procedure TPairs<TKey, TValue>.Add(const aKey: TKey; const aValue: TValue);
begin
SetValue(aKey, aValue);
end;
然後你可以像使用字典一樣使用它,但元素的順序將被保留。
var
Pairs: TPairs<string, string>;
Item: TPair<string, string>;
begin
Pairs := TPairs<string, string>.Create();
Pairs.Add('Key1', 'Text1');
Pairs.Add('Key2', 'Text2');
Pairs.Add('Key3', 'Text3');
Pairs.Add('Key4', 'Text4');
Pairs.Add('Key5', 'Text5');
for Item in Pairs do
begin
Memo1.Lines.Add(Item.Key + ' ' + Item.Value);
end;
end;
SetValue
較新版本的Delphi其中FItems
不TList<T>
子孫類可用的更新。
procedure TPairs<TKey, TValue>.SetValue(Key: TKey; const Value: TValue);
var
i: Integer;
Pair: TPair<TKey, TValue>;
begin
i := IndexOfKey(Key);
if i >= 0 then
begin
Pair := Items[i];
Pair.Value := Value;
Items[i] := Pair;
end
else
begin
Pair.Create(Key, Value);
inherited Add(Pair);
end;
end;
非常感謝! – Marusyk
未標記的條目 左側不能被分配到 過程TPairs .SetValue(Key:TKey; const Value:TValue); var i:整數; 對:TPair ; begin i:= IndexOfKey(Key); if i> = 0 then FItems [i] .Value:= Value << == build, else begin Pair.Create(Key,Value); 繼承添加(Pair); 結束; 結束; –
@MetaMussel在較新的Delphi版本中不再可訪問FItems。我爲這些添加了更新。 –