3

in post: Copy sublist from list was stayed explained me that for copy a sublist in a list need copy single elements doing so:

for iIndex2 := 0 to MyList.Last.Count-1 do 
  MySubList.Add(MyList.Last[iIndex2]); 

I have verified that this method of copy for elements much much highest in list take much time, in order too of some minetes. Trying to simulate with static array in same condition i take few miliseconds, copying all sublist in an array in one time and not for single element. Just for explain better, i have:

program Test_with_array_static;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils, System.Generics.Collections;

type
  TMyArray = array [1..10] of Integer;
  TMyList = TList<TMyArray>;

var
  MyArray: TMyArray;
  MyList: TMyList;
  iIndex1, iIndex2: Integer;
begin
  try
    { TODO -oUser -cConsole Main : Insert code here }

    MyList := TList<TMyArray>.Create;
    try
      for iIndex1 := 1 to 10 do
      begin
        if MyList.Count <> 0 then MyArray := MyList.Last;
        MyArray[iIndex1] := iIndex1;
        MyList.Add(MyArray);
      end;

      for iIndex1 := 0 to Pred(MyList.Count) do
      begin
        for iIndex2 := 1 to 10 do Write(MyList[iIndex1][iIndex2]:3);
        Writeln;
      end;
    finally
      MyList.Free;
    end;

  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;
end.

So i have thinked to use not list as sublist but array and so work, but in my case i don't know in general how much are element in array and need dynamic array for it. I have changed code in:

program Test_with_array_dynamic;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils, System.Generics.Collections;

type
  TMyArray = array of Integer;
  TMyList = TList<TMyArray>;

var
  MyArray: TMyArray;
  MyList: TMyList;
  iIndex1, iIndex2: Integer;
begin
  try
    { TODO -oUser -cConsole Main : Insert code here }

    MyList := TList<TMyArray>.Create;
    try
      SetLength(MyArray, 10);
      for iIndex1 := 1 to 10 do
      begin
        if MyList.Count <> 0 then MyArray := MyList.Last;
        MyArray[iIndex1] := iIndex1;
        MyList.Add(MyArray);
      end;

      for iIndex1 := 0 to Pred(MyList.Count) do
      begin
        for iIndex2 := 1 to 10 do Write(MyList[iIndex1][iIndex2]:3);
        Writeln;
      end;
    finally
      MyList.Free;
    end;

  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;
end.

and so, i have again the problem of before; of course, changing this line:

if MyList.Count <> 0 then MyArray := MyList.Last;

in mode of copy single element, all work. Now i ask, if really not is possible copy an array in a time, without do a copy for single elements, i need it for question of speed only. And time is very much important. Thanks again very much to all that can solve me this problem. Thanks again.

2
  • I cannot make sense of this. Which bit of code is taking minutes, and which is the equivalent code that takes milliseconds? Commented Feb 23, 2012 at 10:40
  • 1
    Hello David, if i have a list of over 1000000 elements (it is mine case, about statistics calc) when i try to copy single elements from a list to other, it take much time, too in order of much minutes. If i make an array dinamically to place of list, it take few milliseconds. The problem with list in this case is ONLY when i copy single element; except for this, the time is "same" (in sense much similar) for both. If you want, i try to reproduce it and post code of both cases. Just tell me if need post ad answer to this, or just as add to original post, it mine bit doubt. Thanks again. Commented Feb 23, 2012 at 11:49

2 Answers 2

3

You need to add a copy of the array. Otherwise, since you keep setting the array variable's length to the same value, you end up working on the same single dynamic array. To make a copy of an array, simply call Copy prior to adding it to your list:

MyList.Add(Copy(MyArray));
Sign up to request clarification or add additional context in comments.

Comments

2

if I understand you correctly, you want to copy memory to improve speed, here's one way to do it:

type
  TMyArray = array of Integer;

procedure CopyMyArraytest;
var
  LSrcArray: TMyArray;
  LDestArray: TMyArray;
  Index: Integer;
begin
  // set the length, can be later changed
  SetLength(LSrcArray, 100);
  // fill the array
  for Index := Low(LSrcArray) to High(LSrcArray) do
    LSrcArray[index] := index;
  // prepare the length of destination array
  SetLength(LDestArray, Length(LSrcArray));
  // copy elements from source to dest, we need Length(LSrcArray) * SizeOf(Integer)
  // because Move needs the number of bytes, we are using "integer" so a simple
  // multiplication will do the job
  Move(LSrcArray[Low(LSrcArray)], LDestArray[Low(LDestArray)], Length(LSrcArray) * SizeOf(Integer));

  // compare elements, just to make sure everything is good
  for Index := Low(LSrcArray) to High(LSrcArray) do
    if LSrcArray[Index] <> LDestArray[Index] then begin
      ShowMessage('NOOO!!!');
      Exit;
    end;
  ShowMessage('All good');
end;

5 Comments

Hello, me like much this solution and work; just a couriosity, is possible apply the MOVE not only for array but too for list of elements? For example in other post: stackoverflow.com/questions/9337775/… Mike W, solved my problem doing to see with a copy of single elements. If is possible to do it too, as i can modify that code where i copy single element with move for to do it? Thanks again very much. About move, i have learned something of new.
if I understand correctly, you should be able to do that, example Move(LSrcArray[15], LDestArray[15], SizeOf(Integer)), but I have not idea how fast would this be compared to LdestArray[15] := LsrcArray[15]; note that in this case I'm copying the 16th element(we start at zero), but you can also copy LDestArray[0] := LSrcArray[15]; use whichever suits you best
my above example copies SizeOf(Integer) which should be 4 on win 32, but it's safer not to assume, hence the SizeOf(Integer), so using Move might note improve the speed, but it's your call
This will work, no doubt, but it is not a general solution. Integer is a blittable type, i.e. a type without reference counting or any other way of managing the lifetime. People looking at this solution should always consider that. Only blittable types can be copied with Move. And this code actually mimics Copy(), which already exists. <g> It is probably a little faster, since Copy() is far more complicated -- it works for all kind of element types -- and must read and react on type information passed at runtime.
Thank you Rudy for completing (:

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.