【问题标题】:How to slice a dynamic array?如何对动态数组进行切片?
【发布时间】:2014-08-15 17:46:53
【问题描述】:

如何将一个动态数组分割成多个子数组? Delphi 中的Slice() 函数不支持动态数组。那么怎么做呢?欢迎使用通用解决方案。

program Project10;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils;

var
  A: Array of Integer;
begin
  SetLength(A, 4);
  Slice(A, 2); // [dcc32 Error] Project10.dpr(15): E2193 Slice standard function only allowed as open array argument
end.

【问题讨论】:

  • 来自文档 (docwiki.embarcadero.com/Libraries/en/System.Slice):仅允许在调用需要开放数组参数的过程或函数时将切片作为参数。
  • @user246408 最好使用Move 而不是 Copy。
  • 如果您使用的是 Move,您需要已经分配的内存才能移动到托管类型并正确处理。 Copy 会为您完成所有这些工作,因为它在内部调用 _DynArrayCopy
  • @StefanGlienke 你可以在原始数组上调用FillChar
  • 然后你突然意识到你原来的数组都是空的。 FillChar 也不是您所要求的通用,因为您需要考虑数组的元素类型来传递要填充的字节数。复制完成所有这些。

标签: delphi delphi-xe6


【解决方案1】:

使用Copy(A, 0, 2) 而不是Slice(A, 2)

关键是要么你需要一个“开放数组参数”(在这种情况下你需要Slice),要么你需要一个常规数组,在这种情况下Copy 将提供一个很好的解决方案。

【讨论】:

【解决方案2】:

可以使用指针从不同的“起点”访问动态数组

考虑代码:

TYPE
  tListArray = ARRAY[0..0] OF CARDINAL; {Or any other type you need}
  tDynamicCardinalArray = ARRAY OF CARDINAL;
VAR
  MyList : tDynamicCardinalArray;
  pArrPos1, pArrPos2 : ^tListArray;
BEGIN
  SetLength(MyList,100);
  pArrPos1 := @MyList[0];
  pArrPos2 := @MyList[50];
  ...
  ...
END;

好处是您可以直接访问,无需复制或移动数据。 缺点是不能在这些数组指针上使用诸如“high”、“low”和“length”之类的函数。或者,如果您想使用结果,至少不会。 在寻址数组指针时,您必须确保永远不会超出 SourceArray MyList 的范围。 好处是它为动态数组带来了多功能性。 众所周知,动态数组只能从 0 .. 到最大大小。 另一边的 pArrPos2 有效地将动态数组呈现为一个数组指针,它也接受负寻址:

pArrPos2^[-50] :=  0; // Equals: MyList[ 0] :=  0
pArrPos2^[  0] := 50; // Equals: MyList[50] := 50
pArrPos2^[ 49] := 99; // Equals: MyList[99] := 99

使用指针,您可以将动态数组“切片”为多个部分,但您必须分别跟踪“高”、“低”和“长度”,至少如果您想要一个完全动态的解决方案可以在软件中即时更改。 所需的额外信息可以作为额外参数传递给过程或函数,并且比实际将数据集复制或移动到新数组中花费的 CPU 时间更少。

我知道。这篇文章很旧,但我仍然认为我的回答在这里/可能是相关的,特别是对于新读者。

【讨论】:

    猜你喜欢
    • 2010-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多