Delphi TList <t>复制到另一个TList?</t>

时间:2014-11-03 19:50:03

标签: delphi tlist

我想知道是否有任何安全的方法将TList元素复制到任何其他TList中 具体位置和具体长度。我应该只将list1的元素分配给list2或 是否有任何功能我不知道哪个处理更准确?

感谢您抽出宝贵时间。

4 个答案:

答案 0 :(得分:4)

我会使用AddRange添加最后的项目,或InsertRange在特定索引上插入项目。

答案 1 :(得分:4)

如果您的意图是 REPLACE 项而不是将它们插入给定位置,那么答案是没有直接机制,迭代分配是使用方法。

for i := 1 to maxItems do
  dest[ insertPos + i - 1] := src[ i - 1 ];

在这种情况下,您应该考虑添加的项目比目的地列表有空间的情况。这是否意味着只更换尽可能多的商品,并且需要添加额外的商品来“腾出空间”。或者根本不分配(除非一切都适合),这是一个只有你的要求可以回答的问题。

但是,如果您打算将 INSERT 项目放入目标列表,那么您可以结合使用 InsertRange()复制()< / strong>与源列表维护的&lt; T&gt; 的内部数组一起使用。例如,使用 TList&lt; String&gt; 的两个实例:

var
  src, dest: TList<String>;
  insertIndex, maxItems: Integer;

dest.InsertRange( insertIndex, Copy( src.List, 0, maxItems ) );

要插入整个 src 列表,您不需要使用 Copy(),但可以直接在 InsertRange()方法:

dest.InsertRange( insertIndex, src );

效果说明:

如果源列表很大和/或添加的子项数量很少,则使用 Copy()是一项可能很昂贵的操作。但是,实际将项目插入目标列表非常有效,因为 InsertRange()方法能够在单个操作中为目标列表中的新项目腾出空间然后插入新项目为他们创建的空间中的项目,因此对于添加的大量项目,它可能仍然被证明是最有效的。

另一种方法是迭代地逐个插入源项目:

for i := 1 to maxItems do
  dest.Insert( insertIndex, src[i - 1]);

虽然这避免了复制插入的数组项,但如果目标列表很大并且插入了大量项目,则迭代插入本身可能效率低,因为目标列表中的每个项目的空间必须分别为每个项目进行插入(虽然通过明确计算和预先分配目的地列表的容量,可以显着改善这种影响。

e.g。如果要将1000个项目列表中的100个项目插入到2000项目列表的(确切)中间:

InsertRange( Copy() )       Copy 100 items into an intermediate array
                            Moves 1000 items in the dest list to make room for 2100 (total)
                            Inserts 100 items into the 'blank' space

Iterative insert            100 repetitions of:
                               Move 1000 items in the dest list to make room for 1 more
                               Inserts 1 item

要插入100个项目, InsertRange()可能效率最高。相比之下,如果仅从源列表中插入单个项目,那么 InsertRange()方法可能会产生过多的开销。

我认为应该是显而易见的,不同的起始条件将决定两种方法中哪一种最有效,如果表现是一个重要问题,应该考虑。

答案 2 :(得分:0)

我假设这两个列表都是通用的TList<T>。并且您正在复制现有项目而不是扩展目标。

在这种情况下,我认为使用for进行分配的:=循环是可行的方法。由于您正在处理通用列表,因此您需要使用可以使用任何泛型类型T的运算符。假设您需要支持托管类型T,那么您无法执行简单的内存复制。这让你有了作业。

答案 3 :(得分:0)

除了Enny的回答,Assign还从目标列表中复制(清除源列表的内容)。

list1 := TList.Create();
for val:=1 to 3 do
    list1.Add(Pointer(val));    // list1 contains {1,2,3}

list2 := TList.Create();
for val:=5 to 8 do
    list2.Add(Pointer(val));    // list2 contains {5,6,7,8}

list2.Assign(list1);            // list2 now contains {1,2,3}
list2.Assign(list1);            // list2 still contains {1,2,3}

list2.Free();
list1.Free();