Delphi字典和订购数据

时间:2015-08-27 21:51:36

标签: delphi dictionary delphi-xe

我的代码是:

procedure TfrmSettings.btnFillDictClick(Sender: TObject);
var
  Dict: TDictionary<string, string>;
  Item: TPair<string, string>;
begin
  Dict := TDictionary<string, string>.Create();

  Dict.Add('Key1', 'Text1');
  Dict.Add('Key2', 'Text2');
  Dict.Add('Key3', 'Text3');
  Dict.Add('Key4', 'Text4');

  for Item in Dict do
  begin
    ShowMessage(Item.Key + ' ' + Item.Value);
  end;    
end;

为什么我几乎每次都在Showmessage中获得不同的价值? 为什么值不按添加顺序存储?

我是德尔福的一个菜鸟,不知道词典的运作方式。而我在谷歌中没有找到任何相关信息。 你能解释一下为什么会这样吗? 有没有办法使用词典而不使用TList&lt;&gt;排序数据?

由于

1 个答案:

答案 0 :(得分:5)

Dictionary不维护元素的顺序,因为它在内部组织为查找表的方式,并且按键的散列排序。它们针对速度进行了优化,而不是为了保持订购。

如果您需要维护元素的顺序,则需要配对列表而不是字典。德尔福没有提供开箱即用的功能。您可以使用以下代码来实现简单的配对列表,并根据您的需要对其进行自定义。

let newstr = String(str.characters.filter {![" ", "\t", "\n"].contains($0)})

然后您可以像使用字典一样使用它,但会保留元素的顺序。

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后代类中没有FItems的新版Delphi版本。

TList<T>