如何在Delphi中合并2个字符串数组

Moj*_*jik 9 arrays delphi

我有2个或更多的动态字符串数组,填充了一些巨大的数据,我想将这个2数组合并到一个数组,我知道我可以用这样的for循环:

var
  Arr1, Arr2, MergedArr: Array of string;
  I: Integer;
begin
  // Arr1:= 5000000 records
  // Arr2:= 5000000 records

  // Fill MergedArr by Arr1
  MergedArr:= Arr1;

  // Set length of MergedArr to length of ( Arra1 + Arr2 )+ 2
  SetLength(MergedArr, High(Arr1)+ High(Arr2)+2);

  // Add Arr2 to MergedArr
  for I := Low(Arr2)+1 to High(Arr2)+1 do
    MergedArr[High(Arr1)+ i]:= Arr2[i-1];
end;
Run Code Online (Sandbox Code Playgroud)

但是对于庞大的数据来说速度很慢,复制阵列内存数据有更快的方式吗?

Cos*_*und 8

首先string是特殊的,所以应该特别对待:不要试图超越编译器,保持代码不变.字符串是特殊的,因为它的引用计数.每次将字符串从一个地方复制到另一个地方时,它的引用计数会递增.当引用计数达到0时,字符串将被销毁.你的代码很好用,因为它让编译器知道你在做什么,反过来编译器有机会正确地增加所有引用计数.

当然,你可以按照gabr答案的评论中的建议玩各种技巧,比如用零填充旧数组,这样新数组中的引用计数仍然有效,但如果你真的需要旧数组,你不能这样做同样.这有点像黑客(虽然可能在可预见的未来有效).(并且要注意,我实际上喜欢这个黑客).

无论如何,这是我的答案的重要部分,你的代码很可能在将字符串从一个数组复制到另一个数组时速度慢,它很可能在其他地方慢慢地.这是一个简短的控制台应用程序,它创建两个数组,每个数组有5M随机字符串,然后将两个数组合并为第三个,并显示创建合并所花费的时间.合并在我的机器上只需要大约300毫秒.填充数组需要更长的时间,但我没有计时:

程序Project26;

{$APPTYPE CONSOLE}

uses SysUtils, Windows;

var a, b, c: array of string;
    i: Integer;

    Freq: Int64;
    Start, Stop: Int64;
    Ticks: Cardinal;

const count = 5000000;

begin
  SetLength(a,count);
  SetLength(b,count);
  for i:=0 to count-1 do
  begin
    a[i] := IntToStr(Random(1));
    b[i] := IntToStr(Random(1));
  end;

  WriteLn('Moving');

  QueryPerformanceFrequency(Freq);
  QueryPerformanceCounter(Start);

  SetLength(c, Length(a) + Length(b));
  for i:=0 to High(a) do
    c[i] := a[i];
  for i:=0 to High(b) do
    c[i+Length(a)] := b[i];

  QueryPerformanceCounter(Stop);
  WriteLn((Stop - Start) div (Freq div 1000), ' milliseconds');
  ReadLn;

end.
Run Code Online (Sandbox Code Playgroud)


gab*_*abr 7

您可以使用内置的Move功能将内存块移动到另一个位置.参数是源和目标内存块以及要移动的数据大小.

因为要复制字符串,所以必须在合并后通过用零填充来销毁源数组.否则,对于字符串的重新计数将是完全错误的,从而导致程序中的破坏和破坏.

var
  Arr1, Arr2, MergedArr: Array of string;
  I: Integer;
begin
  SetLength(Arr1, 5000000);
  for I := Low(Arr1) to High(Arr1) do
    Arr1[I] := IntToStr(I);

  SetLength(Arr2, 5000000);
  for I := Low(Arr2) to High(Arr2) do
    Arr2[I] := IntToStr(I);

  // Set length of MergedArr to length of ( Arra1 + Arr2 )+ 2
  SetLength(MergedArr, High(Arr1)+ High(Arr2)+2);

  // Add Arr1 to MergedArr
  Move(Arr1[Low(Arr1)], MergedArr[Low(MergedArr)], Length(Arr1)*SizeOf(Arr1[0]));

  // Add Arr2 to MergedArr
  Move(Arr2[Low(Arr2)], MergedArr[High(Arr1)+1], Length(Arr2)*SizeOf(Arr2[0]));

  // Cleanup Arr1 and Arr2 without touching string refcount.
  FillChar(Arr1[Low(Arr1)], Length(Arr1)*SizeOf(Arr1[0]), 0);
  FillChar(Arr2[Low(Arr2)], Length(Arr2)*SizeOf(Arr2[0]), 0);

  // Test
  for I := Low(Arr1) to High(Arr1) do begin
    Assert(MergedArr[I] = IntToStr(I));
    Assert(MergedArr[I] = MergedArr[Length(Arr1) + I]);
  end;

  // Clear the array to see if something is wrong with refcounts
  for I := Low(MergedArr) to High(MergedArr) do
    MergedArr[I] := '';
end;
Run Code Online (Sandbox Code Playgroud)