如何在Delphi中将一个数组附加到另 一个相同类型的数组?

问题描述 投票:1回答:3

如何在不使用Delphi中的迭代语句(forwhile循环)的情况下将一个数组附加到另​​一个相同类型的数组?

arrays delphi append delphi-2010
3个回答
2
投票

有两个dynamic arrays arr1arr2

var
  arr1, arr2: array of Integer;
. . .
SetLength(arr1, 3);
arr1[0] := 1;
arr1[1] := 2;
arr1[2] := 3;

SetLength(arr2, 3);
arr2[0] := 4;
arr2[1] := 5;
arr2[2] := 6;

你可以像这样将第一个追加到第二个:

SetLength(arr2, Length(arr2) + Length(arr1));
Move(arr1[0], arr2[3], Length(arr1) * SizeOf(Integer));

System.Move


正如Uwe Raabe's comment指出的那样,您可以对托管类型执行以下操作:

SetLength(arr2, Length(arr2) + Length(arr1));
for i := Low(arr1) to High(arr1) do
  arr2[3+i] := arr1[i];

9
投票

在最后的Delphi版本(XE7 +)中,您可以使用+运算符或Concat例程来追加数组。 LinkOfficial help(未提及+

否则编写自己的过程(如果可能,使用通用数组)。快速示例(在XE3中检查):

type 
TArrHelper = class
  class procedure AppendArrays<T>(var A: TArray<T>; const B: TArray<T>);
end;


class procedure TArrHelper.AppendArrays<T>(var A: TArray<T>;
  const B: TArray<T>);
var
  i, L: Integer;
begin
  L := Length(A);
  SetLength(A, L + Length(B));
  for i := 0 to High(B) do
    A[L + i] := B[i];
end;

用法:

var
  A, B: TArray<String>;
begin
  A := TArray<String>.Create('1', '2', '3');
  B := TArray<String>.Create('4', '5');
  TArrHelper.AppendArrays<String>(A, B);

3
投票

如果你不介意你的原始数组被破坏,那么就有一个hackish解决方案。它可能比循环快很多,因为循环的每次迭代必须添加一个引用,而DestructiveConcatArrays保留引用计数。

这意味着不允许移动要移动的字符串的副本。它们要么在Destination,要么在Source,但不能同时在两者中。否则他们的refcounts无论如何都必须更新 - 循环。

Note

MoveFillChar之间,复制的所有字符串引用都没有正确地重新计算。但在FillChar之后,他们又来了。必须注意,在该不稳定状态下,任何东西,没有线程都应该能够访问Source阵列。

换句话说:以下内容不要求RTL添加或删除引用,但它很棘手并且它会破坏原始(第二个)数组:

procedure DestructiveConcatArrays(var Destination, Source: TArray<string>);
var
  LenD, LenS: Integer;
begin
  LenD := Length(Destination);
  if LenD = 0 then
    Destination := Source
  else
  begin
    LenS := Length(Source);
    if Length(Source) > 0 then
    begin
      SetLength(Destination, LenD + LenS);
      // Copy strings -- Afterwards, the refcounts of all strings copied over are  
      //                 out of sync.
      Move(Source[0], Destination[LenD], LenS * SizeOf(string));
      // Clear Source -- Afterwards, all refcounts are in sync again.
      FillChar(Source[0], LenS * SizeOf(string), 0);
    end;
  end;
  Source := nil;
end;

Careful!

以上不是一般解决方案。这是一个黑客,只为这个目的而设计。但它按预期工作。我测试了那个。但它不是线程安全的,尽管它可能是可行的。


Update

这就是C ++为rvalue表达式移动语义引入的内容。只需将Source视为右值。

© www.soinside.com 2019 - 2024. All rights reserved.