delphipascalfreepascallazarus

Having trouble adding TStringLists with chunks


I am trying to separate data coming from a dataset (Q) into chunks of 10 and place them into a TStringList.

I've create a TStringList called LIST, where every time a record is found it adds a value (UID).

I have tried to use an array of TStringLists to keep track, but it's just a bit cumbersome.

The idea would be, for example, given a dataset that delivers 24 records, LIST can have the first 10 values in LIST.strings[0], records 10 to 20 in LIST.Strings[1], and records 21,22 and 23 in LIST.Strings[2].

Any ideas or directions you might think of? I've tried counters also, and it's just not happening. Should I deal with LIST afterwards?

const chunks = 10
List := TStringList.Create;   
Q.Open;
try
  While not Q.EOF Do
  begin
    UID := Q.FieldByname('U_ID');
    List.Add(UID.AsString);
    Q.Next;
  end;
  Q.Close;
finally
  FreeAndNil(Q);
end;
//SO DESIRED OUTPUT SOMETHING LIKE THIS  
//LIST.COUNT =3
//LIST.STRINGS[0] = 1,2,3,4,5,6,7,8,9,10  
//LIST.STRINGS[1] = 11,12,13,14,15,16,17,18,19,20 
//LIST.STRINGS[2] = 21,22,23               

I have also tried to use Insert(), like this:

List.QuoteChar := ' ';
if List.Count <= 10 then
begin
  MaxList.Insert(0, List.DelimitedText);
end;
if ((List.Count > 10) and (List.Count <= 20)) then
begin
  MaxList.Insert(1, List.DelimitedText);

But Insert() index doesn't work as I want it.


Solution

  • If I understand you correctly, your goal is to store the UIDs as comma-separated strings, where each string holds up to 10 UIDs max. If so, try something like this:

    const
      chunks = 10;
    
    var
      List: TStringList;
      counter: Integer;
    begin
      ...
      counter := 0;
      List := TStringList.Create;   
      try
        Q.Open;
        try
          if not Q.EOF then
          begin
            UID := Q.FieldByName('U_ID');
            repeat
              if (counter mod chunks) = 0 then
                List.Add(UID.AsString)
              else
                List.Strings[List.Count-1] := List.Strings[List.Count-1] + ',' + UID.AsString;
              Inc(counter);
              Q.Next;
            until Q.EOF;
          end;
        finally
          Q.Close;
        end;
        // use List as needed...
      finally
        List.Free;
      end;
      ...
    end;
    

    Alternatively, you can use 2 TStringLists instead of a counter, eg:

    const
      chunks = 10;
    
    var
      List: TStringList;
      Chunk: TStringList;
    begin
      ...
      List := TStringList.Create;   
      try
        Q.Open;
        try
          if not Q.EOF then
          begin
            UID := Q.FieldByName('U_ID');
            Chunk := TStringList.Create;   
            try
              repeat
                if Chunk.Count = chunks then
                begin
                  List.Add(Chunk.CommaText);
                  Chunk.Clear;
                end;
                Chunk.Add(UID.AsString);
                Q.Next;
              until Q.EOF;
              if Chunk.Count > 0 then
                List.Add(Chunk.CommaText);
            finally
              Chunk.Free;
            end;
          end;
        finally
          Q.Close;
        end;
        // use List as needed...
      finally
        List.Free;
      end;
      ...
    end;