2

我想知道是否有任何安全的方法可以将 TList 元素复制到任何其他 TList 到特定位置并具有特定长度。我应该只是将 list1 的元素分配给 list2 还是有任何我不知道的功能可以更准确地处理?

感谢您抽出宝贵时间。

4

4 回答 4

6

我会使用AddRange在末尾追加项目或使用InsertRange在特定索引上插入项目。

于 2014-11-03T20:19:12.273 回答
5

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

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

在这种情况下,您应该考虑添加的项目超出目标列表空间的情况。这是否意味着只更换“适合”的物品,添加额外物品以“腾出空间”或根本不分配任何物品(除非所有物品都适合),这是一个只有您的要求才能回答的问题。

但是,如果您打算将项目插入到目标列表中,那么您可以结合使用InsertRange()Copy()以及由源列表维护的 <T>的内部数组。例如,使用TList<String>的两个实例:

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]);

虽然这避免了复制插入的数组项,但如果目标列表很大并且要插入更多的项,则迭代插入本身可能效率低下,因为必须为每个插入分别为目标列表中的每个项留出空间(尽管通过显式计算和预分配目的地列表的容量,可以显着改善其潜在影响)。

例如,如果您将 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()方法会产生潜在的过多开销。

我认为应该很明显,不同的起始条件将决定这两种方法中的哪一种最有效,如果性能是一个重要问题,则应予以考虑。

于 2014-11-03T20:25:55.823 回答
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();
于 2020-10-01T08:00:08.150 回答
-1

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

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

于 2014-11-03T20:26:24.903 回答