Autor Beitrag
Krefti
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 164

Win XP/Vista/Win7/ubuntu
Delphi 7/2006/2009 Pro
BeitragVerfasst: Di 28.04.09 15:23 
Hallo alle zusammen..

ich hab ein klitzekleines Problem mit einer Sortierung von Strings.
Und zwar ist mein ASCII-File(ca. 30000 Zeilen) nach folgendem Muster aufgebaut:
ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
"2008/01/02","15:16:31.620","4341830","424046","SBI899","United Kingdom","0","3550","3550","49.97783","8.33365","0","-125","0.0","0.0","13920","3660"
"2008/01/02","15:16:31.620","3951383","3C4B17","DLH7PM","Germany","0","4550","4550","49.93491","8.16692","-1088","-1088","211.3","77.1","20497","5011"
"2008/01/02","15:16:32.111","5022462","4CA2FE","","Ireland","0","37000","37000","50.01251","6.39167","0","0","480.7","124.7","1316","0524"
"2008/01/02","15:16:32.111","3754597","394A65","","France","0","31975","31975","49.89885","9.41022","-64","-64","357.5","8.0","8997","2325"
"2008/01/02","15:16:32.111","3146175","3001BF","MYW5300","Italy","0","32025","32025","50.34620","8.28777","-64","-64","414.4","281.6","26128","6610"
"2008/01/02","15:16:32.111","5022309","4CA265","RYR4322","Ireland","0","37000","37000","50.74985","8.18703","0","0","477.8","137.6","21030","5226"
"2008/01/02","15:16:32.121","3958377","3C6669","","Germany","-1","0","0","50.04027","8.56076","0","0","7.5","39.4","30577","7771"
"2008/01/02","15:16:32.121","4456485","440025","AUA124M","Austria","-1","0","0","50.05216","8.53998","0","0","0.5","0.0","29190","7206"
"2008/01/02","15:16:32.121","4981155","4C01A3","JAT351","Yugoslavia","0","9775","9775","49.83623","8.72090","2560","2560","302.6","105.9","8454","2106"
"2008/01/02","15:16:32.121","3958322","3C6632","DLH6JV","Germany","0","10975","10975","50.30846","9.15002","0","0","377.0","212.2","1827","0723"
"2008/01/02","15:16:32.121","3958350","3C664E","","Germany","0","8925","8925","49.91973","9.04398","-960","-960","339.1","284.7","30513","7731"
"2008/01/02","15:16:32.121","3741007","39154F","AFR1645","France","0","35975","35975","50.95613","7.38243","0","0","463.1","228.0","26135","6617"
"2008/01/02","15:16:32.121","4968105","4BCEA9","SXS971","Turkey","0","2000","2000","49.98734","8.52626","2880","2880","163.0","178.9","8550","2166"
"2008/01/02","15:16:32.121","7979027","79C013","CES554","China","0","33000","33000","50.51225","8.49020","0","0","469.1","26.2","1617","0651"
"2008/01/02","15:16:32.131","5022278","4CA246","RYR5706","Ireland","0","5450","5450","50.14723","7.42697","-320","-320","180.9","174.3","0","    "
ich möchte, dass alle, die in der 4. Spalte das gleiche stehen haben untereinander stehen haben..ob absteigend oder aufsteigend sortiert ist mir egal.

Ich hab jetzt mal rumgesucht und weiß nicht, ob ich mit
ausblenden Delphi-Quelltext
1:
TStringlist.Customsort()					

auf dem richtigen Weg bin.
Vielen Dank schon mal für eure Mühe.

Gruß
Krefti

Moderiert von user profile iconNarses: Code-Tags hinzugefügt
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10183
Erhaltene Danke: 1256

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Di 28.04.09 16:10 
Moin!

user profile iconKrefti hat folgendes geschrieben Zum zitierten Posting springen:
ausblenden Delphi-Quelltext
1:
TStringlist.Customsort()					

auf dem richtigen Weg bin.
Jau, würde ich schon sagen. ;)

Ich würde die Strings in eine TStringList einlesen und die .Objects[] zu den Strings auf den Wert in der 4. Spalte setzen (sieht nach 3-Bytes-HEX aus). Dann diesen Wert als Sortierkriterium nehmen. :idea:

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
Krefti Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 164

Win XP/Vista/Win7/ubuntu
Delphi 7/2006/2009 Pro
BeitragVerfasst: Mi 29.04.09 14:06 
hi..

danke schon mal für die Frage und Anregung..

also die von mir ausgewählte Spalte als Sortierkriteritum ist kein hex-code (ich weiß, schaut so aus), sondern eine Flugnummer.
Dieses Felder in der Spalte ist leider nicht immer besetzt, so dass ich mir als Sortierkriteritum nun die 3. Spalte ausgewählt habe.
Kannst du mir evtl. ein kleines Beispiel mit den Objects geben, dass nach diesen Sortiert wird??

Wie ich mir den einzelnen Wert einer Spalte aus einer Zeile hole geht ja einfach mit copy()

Danke schon mal
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10183
Erhaltene Danke: 1256

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Mi 29.04.09 14:12 
Moin!

user profile iconKrefti hat folgendes geschrieben Zum zitierten Posting springen:
Dieses Felder in der Spalte ist leider nicht immer besetzt, so dass ich mir als Sortierkriteritum nun die 3. Spalte ausgewählt habe.
Entscheidende Frage: Ist der Wert im Bereich von Cardinal?

user profile iconKrefti hat folgendes geschrieben Zum zitierten Posting springen:
Wie ich mir den einzelnen Wert einer Spalte aus einer Zeile hole geht ja einfach mit copy()
Ich würde das mit TStringList.CommaText auseinander nehmen. :idea:

user profile iconKrefti hat folgendes geschrieben Zum zitierten Posting springen:
Kannst du mir evtl. ein kleines Beispiel mit den Objects geben, dass nach diesen Sortiert wird?
Sollte machbar sein. ;)

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
Krefti Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 164

Win XP/Vista/Win7/ubuntu
Delphi 7/2006/2009 Pro
BeitragVerfasst: Mi 29.04.09 14:22 
user profile iconNarses hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconKrefti hat folgendes geschrieben Zum zitierten Posting springen:
Dieses Felder in der Spalte ist leider nicht immer besetzt, so dass ich mir als Sortierkriteritum nun die 3. Spalte ausgewählt habe.
Entscheidende Frage: Ist der Wert im Bereich von Cardinal?
Wenn  Cardinal nur bis 65535 geht, dann nicht, denn es ist immer eine 7-stellige Zahl....

user profile iconNarses hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconKrefti hat folgendes geschrieben Zum zitierten Posting springen:
Wie ich mir den einzelnen Wert einer Spalte aus einer Zeile hole geht ja einfach mit copy()
Ich würde das mit TStringList.CommaText auseinander nehmen. :idea:
danke für die :idea: hab da schon so ne kleine prozedur, die ich immer wieder verwende für so dinge ;-)

user profile iconNarses hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconKrefti hat folgendes geschrieben Zum zitierten Posting springen:
Kannst du mir evtl. ein kleines Beispiel mit den Objects geben, dass nach diesen Sortiert wird?
Sollte machbar sein. ;)
hm..okay..funktioniert das dann überhaupt, wenn die werte größer als  Cardinal ist?? wenn nicht, hättest du noch einen alternativen vorschlag??

Moderiert von user profile iconNarses: Beitragsformatierung überarbeitet.

---Moderiert von user profile iconNarses: Beiträge zusammengefasst---

noch mal das, was ich bis jetzt geschrieben habe:
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
slLaden.CustomSort(StringListsortcompare);


function StringListSortCompare(List: TStringList; Index1, Index2: Integer): Integer;
var
  Txt1, Txt2, hTxt1, hTxt2,Subtxt1, subtxt2 : string;

begin
  Txt1 := StringReplace(List[Index1], '"''', [ rfReplaceAll ]);
  Txt2 := StringReplace(List[Index2], '"''', [ rfReplaceAll ]);

  extract(Txt1,',',Subtxt);
  extract(Txt1,',',Subtxt);
  extract(Txt1,',',Subtxt);
  Subtxt1 := copy(Subtxt,1,7);

  extract(Txt2,',',Subtxt);
  extract(Txt2,',',Subtxt);
  extract(Txt2,',',Subtxt);
  Subtxt2 := copy(Subtxt,1,7);
  Result := //??????????????? da weiß ich nicht, was ich hinschreiben muss irgendwas mit compare(subtxt1,subtxt2)??
end;
{ *************************************************************************** }
procedure Extract(var Txt:String;Trenner:Char;var SubTxt:String);
var
   P : Integer;
begin
   P:=POS(Trenner,Txt);
   if P>0 then begin
      SubTxt:=copy(Txt,1,P-1);
      delete(Txt,1,P);
   end
   else begin
      SubTxt:=Txt;
      Txt:='';
   end;
end;
{ *************************************************************************** }
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19312
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mi 29.04.09 14:32 
user profile iconKrefti hat folgendes geschrieben Zum zitierten Posting springen:
Wenn  Cardinal nur bis 65535 geht, dann nicht, denn es ist immer eine 7-stellige Zahl....
Nein, Cardinal ist einiges größer, das geht bis etwas über 4 Milliarden, also reicht es für 7 Stellen in jedem Fall. ;-)

Die Breite der ersten drei Spalten ist immer exakt gleich? Dann könnte man das sehr stark optimieren.

// EDIT:
Dein Quelltext ist allerdings extrem langsam. ;-) Ich poste gleich etwas dazu, wenn du das zur Spaltenbreite bestätigt hast.
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10183
Erhaltene Danke: 1256

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Mi 29.04.09 14:33 
Moin!

user profile iconKrefti hat folgendes geschrieben Zum zitierten Posting springen:
Wenn  Cardinal nur bis 65535 geht, dann nicht, denn es ist immer eine 7-stellige Zahl....
Die DOH würde dir sagen, wie der Wertebereich ist... :les: :zwinker: 32bit ohne Vorzeichen, passt also

Ansatz:
  • ausblenden Delphi-Quelltext
    1:
    var SL: TStringList; // dem Kind einen Namen geben					

  • SL mit den Zeilen füllen
  • ausblenden Delphi-Quelltext
    1:
    SL.Objects[i] := Pointer(1234567); // hier den tatsächlichen Wert ermitteln					

  • diese Funktion verwenden:
    ausblenden Delphi-Quelltext
    1:
    2:
    3:
    4:
    function MySLCompare(StringList: TStringList; Index1, Index2: Integer): Integer;
    begin
      CompareValue(Cardinal(StringList.Objects[Index1]),Cardinal(StringList.Objects[Index2]));
    end;

  • so aufrufen: SL.CustomSort(MySLCompare);
cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
Krefti Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 164

Win XP/Vista/Win7/ubuntu
Delphi 7/2006/2009 Pro
BeitragVerfasst: Mi 29.04.09 14:33 
ja, die spalten sind immer gleich breit..
datum und uhrzeit und die 3. spalte is die meine;)

wie könnte man das optimieren?? ich bin für jede anregung und tip zu meinem quelltext dankbar, speziell die stelle, wo result steht und ich nicht genau weiß, was da hin kommen muss....

@narses

und wo muss ich das hinschreiben?? in meine procedure wo ich customsort aufrufe??
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19312
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mi 29.04.09 14:52 
Das hier sollte eine sehr schnelle Lösung sein:
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
procedure TForm170.Button1Click(Sender: TObject);

  function ExtractThirdCol(ALine: String): Cardinal;
  var
    Value: String;
  begin
    SetLength(Value, 7);
    CopyMemory(Pointer(Value), Pointer(Integer(Pointer(ALine)) + 29), 7);
    Result := StrToInt(Value);
  end;

  function StringListSortCompare(List: TStringList; Index1, Index2: Integer): Integer;
  var
    Value1, Value2: Cardinal;
  begin
    Value1 := Cardinal(List.Objects[Index1]);
    Value2 := Cardinal(List.Objects[Index2]);
    if Value1 < Value2 then
      Result := -1
    else if Value1 = Value2 then
      Result := 0
    else
      Result := 1;
  end;

var
  Temp: TStringList;
  i: Integer;
begin
  Temp := TStringList.Create;
  try
    Temp.LoadFromFile(...);
    for i := 0 to Temp.Count - 1 do
      Temp.Objects[i] := TObject(ExtractThirdCol(Temp[i]));
    Temp.CustomSort(@StringListSortCompare);
    Temp.SaveToFile(...);
  finally
    Temp.Free;
  end;
end;
Je nach Art der Daten könnte auch eine eigene Sortierimplementierung sinnvoll sein. Aber bei 30.000 Zeilen sollte auch das schon schnell genug sein.

user profile iconKrefti hat folgendes geschrieben Zum zitierten Posting springen:
wie könnte man das optimieren??
Dadurch, dass du das relativ langsame StringReplace benutzt und zusätzlich den String ständig veränderst (was im übrigen auch bei einer allgemeinen Auswertung unüberlegt und unnötig langsam ist) wird das sehr langsam.
Krefti Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 164

Win XP/Vista/Win7/ubuntu
Delphi 7/2006/2009 Pro
BeitragVerfasst: Do 30.04.09 07:29 
Guten morgen zusammen,

war gerade dabei den Vorschlag von Jaenick auszuprobieren...

Copymemory ist eine funktion die das delphi bereitstellt?? weil wenn ich in der hilfe über den index danach suche findet er nix....*scratch*

Bzw. welche Unit muss ich dazu einbinden um copymemory zu verwenden??
danke schon mal für eure fleißige hilfe!!

gruß
krefti

---Moderiert von user profile iconNarses: Beiträge zusammengefasst---

habs gefunden, welche unit ich brauch..die windows..


mir ist jetzt beim ersten durchlauf aufgefallen, dass die 3. spalte nicht imm 7 Zeichen hat..können auch 6 sein..des is des erste mal in zeile 23487 aufgetreten..danach kommts öfters...

Wäre das mit deinem vorgeschlagenen extracht und sortieralgorythmus variabel machbar und einfach zu lösen??
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10183
Erhaltene Danke: 1256

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Do 30.04.09 10:02 
Moin!

user profile iconKrefti hat folgendes geschrieben Zum zitierten Posting springen:
mir ist jetzt beim ersten durchlauf aufgefallen, dass die 3. spalte nicht imm 7 Zeichen hat..können auch 6 sein..des is des erste mal in zeile 23487 aufgetreten..danach kommts öfters...
Spätestens jetzt wüde ich den Ansatz auf Basis fester Spalten sein lassen und das ganze CSV-konform per TStringList.CommaText machen, das klappt dann immer. :idea: :D

Ansonsten könnte es nicht schaden etwas Energie in das Verständnis des vorgeschlagenen Codes zu investieren; bisher scheint mir das doch etwas sehr viel c&p-Vorgehen zu sein... :? :nixweiss:

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
Krefti Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 164

Win XP/Vista/Win7/ubuntu
Delphi 7/2006/2009 Pro
BeitragVerfasst: Do 30.04.09 11:41 
@narses

also ich habs jetzt erstmal so umgesetzt, dass es auf basis der spalten bassiert..is wahrscheinlich kein optimiertr sortier prozess, aber es funktioniert jetzt erstmal..

hab schon vorher deinen rat befolgt gehabt, dass ich ein bischen energie und zeit in das verstehen des codes investiert habe ;-)

was heißt denn csv-konform??

bei gelegeheit werd ich mir auf jedenfall mal die tstringlist.commatext anschauen..
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10183
Erhaltene Danke: 1256

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Do 30.04.09 12:10 
Moin!

user profile iconKrefti hat folgendes geschrieben Zum zitierten Posting springen:
was heißt denn csv-konform??

bei gelegeheit werd ich mir auf jedenfall mal die tstringlist.commatext anschauen..
Ginge z.B. so: ;)
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
function ExtractCol(const ALine: Stringconst ACol: Integer): Cardinal;
  var
    SL: TStringList;
begin
  SL := TStringList.Create;
  try
    SL.CommaText := ALine;
    if (SL.Count > ACol) then
      Result := StrToInt64Def(SL.Strings[ACol],0)
    else
      Result := 0;
  finally
    SL.Free;
  end;
end;
Allerdings ist das Erzeugen der Stringliste in der Funktion natürlich ein Performance-Killer; das sollte man ausserhalb der Schleife tun, die die Zeilen analysiert. :idea:

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19312
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Do 30.04.09 14:38 
Also mein Vorschlag wäre dann, wenn sich nur die Größe der dritten Spalte ändert, das Endzeichen zeichenweise zu suchen. Ändert sich doch auch die der ersten beiden Spalten, dann würde ich von vorne her zeichenweise durchgehen und die Vorkommen der ; außerhalb von " " zählen um die Spalte zu finden.
Krefti Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 164

Win XP/Vista/Win7/ubuntu
Delphi 7/2006/2009 Pro
BeitragVerfasst: Mo 04.05.09 15:39 
also ich hab jetzt mal alles soweit hinbekommen.

jetzt hab ich aber noch den Auftrag bekommen, dasss ich zuätzlich noch nach der Uhrzeit sortieren soll.

also erst nach der 3. Spalte und dann nach der 2. Spalte.

jetzt weiß ich nicht, da das ja, nachdem ich die doppelpunkte rausgenommen habe, eine Kommazahl als String ist, wie ich den sortieren kann und wie ich die 2 Sortierkriterien miteinander, am Besten in einer routine, verknüpfen kann.
Ich hatte die Uhrzeit auch erstmal zu einem Cardinal gemacht und versucht so wie in der anderen Routine zu sortieren, aber damit hab ich meine vorherige Sortierung wieder durcheinander gebracht, weil Delphi ja nicht der Reihe nach miteinander vergleich.

Wäre super, wenn ihr mir noch einmal helfen könntet.
Vielen Dank schon mal!!
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19312
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mo 04.05.09 15:42 
Dann brauchst du ein stabiles Sortierverfahren.
Krefti Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 164

Win XP/Vista/Win7/ubuntu
Delphi 7/2006/2009 Pro
BeitragVerfasst: Di 05.05.09 12:43 
also leute..ich habs jetzt noch ganz anderst gemacht.

ich hab den string der 2. spalte an die 3. spalte angehängt und dann einfach mit
ausblenden Delphi-Quelltext
1:
strcomp					


sortieren lassen. Weiß gar nicht, warum ich es so complicated machen wollte.

vielen dank leute noch mals..

gruß krefti