Avatar billede friiiiis Novice
29. april 2008 - 10:09 Der er 10 kommentarer og
1 løsning

dataset til dynamisk array

Hej,

jeg bruger følgende kode for at overføre data fra et dataset til et dynamisk array

  i := 1;
  repeat
    VarLineCharacteristics[i,1] = DataSource1.DataSet.Fields[2].Value
    DataSource1.DataSet.MoveBy(1);
    Inc(i);
  until DataSource1.DataSet.EOF;


Problemet er at denne metode er LANGSOM... er der ikke en hurtigere metode...?

Et sidste spørgsmå - hvordan finder jeg ud af hvor mange rækker af data der er i et field??
Avatar billede hrc Mester
29. april 2008 - 11:42 #1
Nej du vil ikke! Du skal ikke bruge dynamiske arrays til den slags. Det er dumt, foruden som du selv har bemærket, langsomt.

Hvis du gerne vil arbejde på data i hukommelsen kan du bruge:
  1. En liste nedarvet fra TObjectList
  2. En liste nedarvet fra TDataSet
  3. En liste baseret på TClientDataSet

ad. 1: Her har du 100% kontrol over hvad der skal ske. Ulempen er at du skal programmere lidt mere (men alt er bedre end dynarrays). Min favorit, men jeg er også lidt gammeldags.

ad. 2: En liste som du kan traversere på samme måde som en TTable. Ulempen er at det bruger en del ram. Til at kopiere kan du bruge TBatchMove.

ad. 3: Med TClientDataSet har du data liggende i hukommelsen, meget ligesom TTable, men lavet rigtigt kan du slippe for at kopiere til andet dataset. Også en favorit, men lidt omstændig at sætte op med kæden af et TClientDataSet, TDataSetProvider og en TQuery (afh. af database)
Avatar billede friiiiis Novice
29. april 2008 - 13:03 #2
det lyder rigtigt godt - har du noget eksempel på kode så skal jeg nok give dig pointene...

det lyder som om at ad 1) "en liste nedarvet fra TObjectList" lyder som det lettest gennemførlige...
Avatar billede hrc Mester
29. april 2008 - 13:27 #3
Tak for det. Nu er det ikke første gang jeg plæderer for at man bruger TObjectList fremfor ... stort set alt andet, men især DynArrays.

  http://www.eksperten.dk/spm/528142

Her er også noget hvor du kan se hvordan jeg propper data i et listview og hvordan man sorterer kolonnerne:

  http://www.eksperten.dk/spm/684246
Avatar billede friiiiis Novice
29. april 2008 - 14:58 #4
Hej,

ja, det er jo kun 60 point, så du skal vel egentlig have nogle flere point for det her...

her kommer lige et spørgsmål mere til http://www.eksperten.dk/spm/528142

Det virker som om at Data[i][j][k] er en form tredimensional array - men det kan jeg ikke se udfra "Type" definitionen.


- Altså: jeg er med på koden herunder:

procedure TfrmMain.Button1Click(Sender: TObject);
var
  Data : TDataList;
  i,j,k : integer;
begin
  Data := TDataList.Create('test.txt');
  try
    for i := 0 to Data.Count - 1 do begin
      mLog.Lines.Add(format('%s %d',[Data[i].Field1,Data[i].Field2]));
      for j := 0 to Data[i].Count - 1 do
        for k := 0 to Data[i][j].Count - 1 do
          mLog.Lines.Add(Data[i][j][k]);
    end;
  finally
    Data.Free;
  end;
end;


men ikke hvordan man går fra type definitionen

type
  TDataList = class;
  TSegmentData = class;
  TSegmentSubData = class;

  TDataList = class(TObjectList)
  private
    fFileName : string;
    function GetSegmentData(const aIndex: integer): TSegmentData;
  public
    constructor Create(const aFileName : string);
    property FileName : string read fFileName;
    property Items[const aIndex : integer] : TSegmentData read GetSegmentData; default;
  end;



og så over til Data[i][j][k]??

Jeg vil gerne give dig flere pont for det - er forslag til point?
Avatar billede hrc Mester
29. april 2008 - 21:56 #5
Hvis du kigger på de tre klassedefinitioner er de alle lister. Den sidste er en TStringList mens de to første er TObjectLister. De har alle en properties (a.k.a. attribut) med et "default" bagefter. Det er en genvej der betyder man ikke behøver skrive MyObject.Items[i], men kan nøjes med MyObject[i]. Da klasserne hænger i enden af hinanden kan man netop skrive "Data[i][j][k]"

Uden "default" havde linjen heddet "Data.Items[i].Items[j].Items[k]"
Avatar billede hrc Mester
29. april 2008 - 22:03 #6
Tanken bag eksemplet var at løsningen skulle være dynamisk. Hele skidtet kan vokse i alle retninger uden der behøver ændres en tøddel (eller bare lidt) i koden.
Eksemplet morede mig; det er simpel objektorientering men ydelse og ram-forbrug kan være et problem. Tror man kan hente en del ved at ændre TSegmentSubData til en fast array af integers, eller måske endda erstatte klassen med en "packed record"
Avatar billede friiiiis Novice
08. maj 2008 - 10:16 #7
Hej igen igen...

Jeg har nu prøvet med koden:

  repeat
    DataSource1.DataSet.MoveBy(1);
    Inc(Y);
  until DataSource1.DataSet.EOF;

bare for at se hvor hurtigt det går - og det går LANGSOMT!!! dvs. det er ikke overførslen fra dataset til dynamisk arry der er problemet - det er simpelthen

DataSource1.DataSet.MoveBy(1)

der er langsomt...

Kan man ikke overføre en kolonne i "Dataset" til stringlist eller andet (objectlist f.eks) UDEN BRUG AF DataSource1.DataSet.MoveBy(1) og så benytte den i den videre databehandling... det vil gøre det hele MEGET hurtigere...??

altså, f.eks.

var
agubsa :Tstringlist
begin

agubsa.assign(DataSource1.DataSet.fields[2]);

ovenstående virker ikke, men noget i den stil ville være meget interssant!!!
Avatar billede hrc Mester
08. maj 2008 - 11:27 #8
Nu prøver jeg at RÅBE det ud: Drop de dynamiske arrays! De dur' ikke til det du vil bruge dem til.

Hvad den anden ting angår:

DataSource1.DataSet.First;
while not DataSource1.DataSet.Eof do
begin
  ...
  DataSource1.DataSet.Next;
end;

Det er den eneste rigtige måde at gennemløbe en tabel. Her undgår du fejl hvis den forsøger rykke rundt i en tom tabel.

Hvad assign angår skal parameteren være nedarving af samme klasse. For TStringList er det TStrings der er ankerklassen. Det er jo også vrøvl at prøve at kopiere kage til ost, :-)
Avatar billede friiiiis Novice
08. maj 2008 - 11:50 #9
hrc: det var ikke dynamiske array's jeg hentydede til - den har jeg forstået :-))

Det er simpelthen bare om man ikke kan overføre en kolonne fra dataset til f.eks. en Obejctlist, en stringlist eller noget andet istedet for at gennemløbe hele databsen. Det er såmænd bare det jeg henviser til /spørger til...

His jeg bruger dit eksempel med TObjectlist så skal jeg jo stadigvæk gennemløbe hele datasettet = langsomt...

Kan jeg bruge Tbacthmove?
Avatar billede hrc Mester
10. maj 2008 - 13:01 #10
friiiiiis: Jeg tror ikke min version er langsom. Det tror jeg derimod godt din version kan være (hvis ikke den bare indkapsler Query.Next og Query.Prev). Det tager ingen tid at gennemløbe mange records. Det jeg kan mistænke er at, du på en eller anden måde, trigger noget kode. Altså noget med at BeginUpdate/EndUpdate.

Jeg er ret sikker på at TBatchMove laver en lo-level "while not query.eof" som ikke er meget hurtigere. Men jo, den kan godt bruges - måske i forbindelse med et TClientDataSet.
Avatar billede friiiiis Novice
13. maj 2008 - 22:29 #11
jeg fandt den her artikel:

http://dn.codegear.com/article/27790

ret interessant...

resumeet af artiklen er egentlig bare: HUSK at skriv:"DisableControls;"...
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester