How to slice a dynamic array?
Asked Answered
O

2

5

How can I slice a dynamic array to multiple sub arrays? Slice() function in Delphi does not support dynamic arrays. So how can it be done? A generic solution would be welcome.

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.
Outofdoor answered 25/6, 2014 at 8:43 Comment(5)
From the docs (docwiki.embarcadero.com/Libraries/en/System.Slice): Slice is only allowed as a parameter in a call to a procedure or function that expects an open array parameter.Ecuador
@user246408 Might aswell use Move instead of Copy.Outofdoor
If you are using Move you need already allocated memory to move to and proper handling of managed types. Copy does all that for you because it internally calls _DynArrayCopy.Romulus
@StefanGlienke You can call FillChar on the original array.Outofdoor
And then you suddenly realize that your original array is all empty. Also FillChar is not generic as you asked for because you need to consider the element type of the array to pass the count of bytes to fill. Copy does all that.Romulus
M
8

Use Copy(A, 0, 2) instead of Slice(A, 2).

The point is that either you need an "open array parameter" (in which case you need Slice) or you need a regular array, in which case Copy will provide a good solution.

Mudskipper answered 25/6, 2014 at 8:51 Comment(1)
As for the "open array parameter" suggestion with Slice() for a dynamic array, you must use type casting to make it work. See Slice does not work with dynamic arrays. Or see this post, Passing slice of a static/dynamic array by reference with start and length specifier, for a solution that also gives an offset possibility.Palazzo
G
1

It is possible to use pointers in order to access a Dynamic Array from different "start points"

Consider the code:

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;

The benefit is that you have direct access, no copying or moving of data involved. The drawback is that functions such as "high", "low" and "length" CAN NOT be used on these array-pointers. Or at least not if you want a result to use. You have to make sure that you never go beyond the scope of the SourceArray MyList when you address the array-pointers. The benefit is that it brings versatility to Dynamic Arrays. As we know, a Dynamic Array can only be created from 0 .. and up to the size. pArrPos2 on the other side has effectively rendered the Dynamic Array into an Array-Pointer which also accept negative addressing:

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

Using pointers, you can "slice" a Dynamic Array into several pieces, but you have to keep track of the "High", "Low", and "Length" separately, at least if you want a fully dynamic solution that can be changed on the fly in software. The needed extra information can be passed as an extra parameter to a procedure or function and takes less CPU-time than actually copying or moving a dataset into a new array.

I know. the post was old, but I still think my answer would/could be relevant here, in particular for new readers.

Grigson answered 18/1, 2017 at 5:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.