【问题标题】:Is there an easy way to copy the TDictionary content into another?有没有一种简单的方法可以将 TDictionary 内容复制到另一个中?
【发布时间】:2012-04-04 22:46:57
【问题描述】:

是否有一种方法或简单的方法可以将一个 TDictionary 内容复制到另一个? 假设我有以下声明

type
  TItemKey = record
    ItemID: Integer;
    ItemType: Integer;
  end;
  TItemData = record
    Name: string;
    Surname: string;
  end;
  TItems = TDictionary<TItemKey, TItemData>;

var
  // the Source and Target have the same types
  Source, Target: TItems;
begin
  // I can't find the way how to copy source to target
end;

我想将 Source 1:1 复制到 Target。有这样的方法吗?

谢谢!

【问题讨论】:

    标签: delphi generics delphi-xe2 deep-copy tdictionary


    【解决方案1】:

    TDictionary 有一个构造函数,允许您传入另一个集合对象,该对象将通过复制原始内容来创建新的集合对象。这就是你要找的吗?

    constructor Create(Collection: TEnumerable<TPair<TKey,TValue>>); overload;
    

    所以你会使用

    Target := TItems.Create(Source);
    

    Target 将被创建为 Source 的副本(或至少包含 Source 中的所有项目)。

    【讨论】:

      【解决方案2】:

      如果你想走得更远,这里有另一种方法:

      type
        TDictionaryHelpers<TKey, TValue> = class
        public
          class procedure CopyDictionary(ASource, ATarget: TDictionary<TKey,TValue>);
        end;
      
      ...implementation...
      
      { TDictionaryHelpers<TKey, TValue> }
      
      class procedure TDictionaryHelpers<TKey, TValue>.CopyDictionary(ASource,
        ATarget: TDictionary<TKey, TValue>);
      var
        LKey: TKey;
      begin
        for LKey in ASource.Keys do
          ATarget.Add(LKey, ASource.Items[ LKey ] );
      end;
      

      根据您对KeyValue的定义使用:

      TDictionaryHelpers<TItemKey, TItemData>.CopyDictionary(LSource, LTarget);
      

      【讨论】:

      • 我认为这会更快:var Item: TPair&lt;TKey,TValue&gt;; ... for Item in ASource do ATarget.Add(Item.Key, Item.Value);
      【解决方案3】:

      我认为这应该可以解决问题:

      var
        LSource, LTarget: TItems;
        LKey: TItemKey;
      begin
        LSource := TItems.Create;
        LTarget := TItems.Create;
        try
          for LKey in LSource.Keys do 
            LTarget.Add(LKey, LSource.Items[ LKey ]);
        finally
          LSource.Free;
          LTarget.Free;
        end; // tryf
      end;
      

      【讨论】:

      • 你能解释一下为什么你分配 LNewKey := LKey;而不是在表达式中使用 Lkey 两次 LTarget.Add(LKey, LSource.Items[ LKey ]);
      • 我认为这会更快:var Item: TPair&lt;TKey,TValue&gt;; ... for Item in LSource do ATarget.Add(Item.Key, Item.Value);
      【解决方案4】:

      在打算分配时构造一个新实例可能会产生副作用,例如其他地方的对象引用失效。泛型方法可能不会深度复制引用的类型。

      我会采用更简单的方法:

      unit uExample;
      
      interface
      
      uses
        System.Generics.Collections;
      
      type 
        TStringStringDictionary = class(TDictionary<string,string>)
        public
          procedure Assign(const aSSD: TStringStringDictionary);
        end;
      
      implementation
      
      procedure TStringStringDictionary.Assign(const aSSD: TStringStringDictionary );
      var
        lKey: string;
      begin
        Clear;
        for lKey in aSSD.Keys do
          Add(lKey, aSSD.Items[lKey]); // Or use copy constructors for objects to be duplicated
      end;
      
      end.
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-11-01
        • 2011-02-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多