Delphi-PRAXiS
Seite 3 von 3     123   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Code Optimierung (https://www.delphipraxis.net/117590-code-optimierung.html)

nahpets 22. Jul 2008 09:40

Re: Code Optimierung
 
Hallo,

wenn Du kein Array der passenden Größe machen kannst, dann mach doch 100.
Eins für 0 bis 99999, eins für 100000 bis 199999 ....
Per Case könntest Du dann nach iID-Bereich abfragen und entscheiden, in welches Array Du die Summe speichern muss.

Naja, diese Lösung ist dann suboptimal und grenzt schon an Gefrickel, aber wenn's funktioniert...

Wofür wird bitteschön der ganze Spaß gebraucht und wie ist mit der Verteilung der IDs zu rechnen?
Gibt es da irgendwelche Bereiche von IDs, die überhaupt nur infrage kommen. Dann läßt sich das Array ja durch anpassen von min und max auf diesen Bereich einschränken ohne dass die übrige Logik davon betroffen wird.
Zumindest von der Zeilenzahl der Liste, kann jede ID 1,3mal vorkommen. Die Hashmap muss dann auch entsprechend groß werden können.

Stephan

Diamondback2007 22. Jul 2008 10:09

Re: Code Optimierung
 
Ähm naja das sind Daten aus dem medizinischen Bereich. Kann ich euch also nicht allzu viel zu sagen.
Es geht nur darum erst mal alle doppelten zu finden und zu addieren und danach alle IDs die die selbe Summe an PZNs haben zu einer Gruppe zusammenzufassen.
Die Hashmap ist groß genug, die vergrößert sich von selber :)

angos 22. Jul 2008 10:17

Re: Code Optimierung
 
--

alzaimar 22. Jul 2008 10:30

Re: Code Optimierung
 
Zitat:

Zitat von Diamondback2007
So, ich hätte jetzt folgenden Code:
...
Sollte das so klappen?

Nein. Du willst die Adresse der lokalen Variablen speichernm aber tmpPZN wird jedesmal verändert. Entweder Du veränderst die Hashmap, sodaß sie bei einem gefundenen Schlüssel die Data-Information gleich überarbeitet, oder Du erzeugst jedesmal Dir dynamisch einen Integer:
Mach es so:
Delphi-Quellcode:
Type
  PInteger = ^Integer;

Var
  Data : PInteger;
  sID : String;

for i := 0 to sl.Count - 1 do Begin
  tmpPZN := StrToInt32_JOH_IA32_7_a(ExtractPZN(sl.Strings[i]));
  sID := ExtractID(sl.Strings[i]);
  if not StringDic.Find(sID, Pointer (Data)) then begin
    New (Data);
    Data^ := tmpPZN;
    StringDic.Add(sID, Data);
  end
  else
    Inc(Data^, tmpPTN);
end;
Achtung! Hinterher aber die Data wieder mit Dispose freigeben! Dazu wanderst Du per 'First/Next durch die Hashmap und gibst einzeln die gelieferten Data wieder frei.
Delphi-Quellcode:
StringDic.First;
While StringDic.Next (sID, PInteger (Data)) Do
  Dispose (Data);
Große Arrays erzeugt man übrigens dynamisch.
Delphi-Quellcode:
Var
  BigArray : Array Of Integer;

Begin
  SetLength(BigArray, 10000000);

Diamondback2007 22. Jul 2008 10:59

Re: Code Optimierung
 
Achs
Zitat:

Zitat von alzaimar
Zitat:

Zitat von Diamondback2007
So, ich hätte jetzt folgenden Code:
...
Sollte das so klappen?

Nein. Du willst die Adresse der lokalen Variablen speichernm aber tmpPZN wird jedesmal verändert. Entweder Du veränderst die Hashmap, sodaß sie bei einem gefundenen Schlüssel die Data-Information gleich überarbeitet, oder Du erzeugst jedesmal Dir dynamisch einen Integer:
Mach es so:
Delphi-Quellcode:
Type
  PInteger = ^Integer;

Var
  Data : PInteger;
  sID : String;

for i := 0 to sl.Count - 1 do Begin
  tmpPZN := StrToInt32_JOH_IA32_7_a(ExtractPZN(sl.Strings[i]));
  sID := ExtractID(sl.Strings[i]);
  if not StringDic.Find(sID, Pointer (Data)) then begin
    New (Data);
    Data^ := tmpPZN;
    StringDic.Add(sID, Data);
  end
  else
    Inc(Data^, tmpPTN);
end;
Achtung! Hinterher aber die Data wieder mit Dispose freigeben! Dazu wanderst Du per 'First/Next durch die Hashmap und gibst einzeln die gelieferten Data wieder frei.
Delphi-Quellcode:
StringDic.First;
While StringDic.Next (sID, PInteger (Data)) Do
  Dispose (Data);
Große Arrays erzeugt man übrigens dynamisch.
Delphi-Quellcode:
Var
  BigArray : Array Of Integer;

Begin
  SetLength(BigArray, 10000000);


Okay vielen Dank erst einmal :) Dann werde ich mich mal damit beschäftigen ;)
Wenn man das Array dynamisch erzeugt klappts dann auch größer oder was? :)

Diamondback2007 22. Jul 2008 11:32

Re: Code Optimierung
 
Also das mit dem Array scheint nicht zu funktionieren, dafür das mit der Hashmap aber umso besser :)
Also wenn die Daten die da jetzt rausgekommen sind wirklich stimmen, dann :shock: .
Er braucht jetzt für die 13 Millionen Einträge kürzer als vorher für 100.000 :lol: .
Also vielen Dank schonmal :) :) .
Das war ja eine super Hilfe :dp:

Diamondback2007 22. Jul 2008 11:52

Re: Code Optimierung
 
Hmmm... Ich habe noch etwas Probleme, die Werte aus der Map auszulesen...
Hier mal mein Code:
Delphi-Quellcode:
  StringDic.First;
  ListBox1.Items.BeginUpdate;
  for i := 0 to StringDic.TotalCount - 1 do
    begin
      StringDic.Next(sID, tmpData);
      ListBox1.Items.Add('ID: ' + sID + ' Summe: ' + IntToStr(Integer(tmpData^)));
    end;
  ListBox1.Items.EndUpdate;
So, an sich klappt das nur leider bekomme ich dann Integer Überläufe angezeigt, also halt negative Werte.
Nehme ich nun beim Casten Int64 anstatt Integer, so kommen vollkommen falsche Werte herraus.
Was kann man dagegen tun?

Diamondback2007 22. Jul 2008 12:11

Re: Code Optimierung
 
Okay, Problem gelöst. Ich musste natürlich Data nicht als PInteger sondern als PInt64 deklarieren.
Hier der gesamte Code:

Delphi-Quellcode:
var
  StringDic                  : TStringDictionary;
  tmpPZN                     : Integer;
  Data                       : PInt64;
  sl                         : TStringList;
  sID                        : string;

[...]

    for i := 0 to sl.Count - 1 do
      begin
        tmpPZN := StrToInt32_JOH_IA32_7_a(ExtractPZN(sl.Strings[i]));
        sID := ExtractID(sl.Strings[i]);
        if not StringDic.Find(sID, Pointer(Data)) then
          begin
            New(Data);
            Data^ := tmpPZN;
            StringDic.Add(sID, Data);
          end
        else
          begin
            Inc(Data^, tmpPZN);
          end;
      end;
Vielen Dank :)

alzaimar 22. Jul 2008 12:14

Re: Code Optimierung
 
Delphi-Quellcode:
Var
  tmpData : PInteger;

Begin
  StringDic.First;
  ListBox1.Items.BeginUpdate;
  while StringDic.Next(sID, tmpData) do
    ListBox1.Items.Add('ID: ' + sID + ' Summe: ' + IntToStr(tmpData^));
  ListBox1.Items.EndUpdate;
End;
Bei mir funktioniert das tadellos auch mit PInteger. Hast Du Data etwa schon wieder per Dispose freigegeben?

Diamondback2007 22. Jul 2008 12:21

Re: Code Optimierung
 
Ich darf halt tmpData nicht als PInteger deklarieren... Dann gibt er mir den fehler dass die Parameter stimmen müssen. Ich brauche also einen untyped Pointer. Außerdem reicht Integer halt nicht aus von der Größe. Bei 13 Millionen Einträgen kommt da was zusammen ;)


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:18 Uhr.
Seite 3 von 3     123   

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz