Hallo alzaimar,
Zitat von
alzaimar:
1. Ermittle die Delimiter-Positionen (
GetStartPos und
GetNextPos) je Zeile einmal im Vorfeld und speichere die Ergebnisse zwischen. Dadurch werden redundante Mehrfachaufrufe vermieden.
2. Die Funktionen
GetStartPos und
GetNextPos sollten private Methoden deiner Klasse werden
3. Deine Sorge bezüglich des 'MyCompare'-Funktion ist unbegründet. Keiner wird je diese Funktion zu Gesicht bekommen, sie ist doch lokal in der
Unit und damit unsichtbar. Entferne die Prüfung 'If item is...', denn das brauchst Du doch nicht und es frisst Performance.
da komm' ich jetzt nicht so ganz mit:
Zitat:
2. Die Funktionen GetStartPos und GetNextPos sollten private Methoden deiner Klasse werden
dann kenne ich sie in MyCompare nicht mehr. In MyCompare müsste ich dann mit einem Konstrukt wie
Delphi-Quellcode:
with List as TSortStringList do begin
.
.
.
end;
arbeiten, um doch an GetStartPos und GetNextPos zu kommen.
Für die vorab ermittelten Positionen brauche ich also entsprechende Attribute in der Klasse, in denen ich die Ergebnisse der Funktionen GetStartPos und GetNextPos vorhalte, die entsprechend Deinem Vorschlag vorher ermittelt wurden. Hier könnte dann ein dynamisches Array mit 'nem Record der Form
Delphi-Quellcode:
type
rPosData = record
StartPos : Word;
NextPos : Word;
end;
.
.
.
fPosData = Array of rPosData;
.
.
.
herhalten und in
Delphi-Quellcode:
procedure TSortStringList.Compare;
Var
i : Integer;
iPos : Integer;
iPosLast : Integer;
begin
SetLength(fPosData,Self.Count);
for i := 0 To Self.Count - 1 Do begin
iPos := GetStartPos(Self[i],Self.Delimiter,fSortColumn);
iPosLast := GetNextPos(Self[i],Self.Delimiter,iPos)
fPosData[i].StartPos := iPos;
fPosData[i].NextPos := iPosLast;
end;
Self.CustomSort(MyCompare);
end;
füllen wir das Array.
Als Ergebnis von MyCompare werden von CustomSort Einträge der Stringliste vertauscht. Wie bekomme ich denn da eine Synchronisation der vertauschen Einträge mit den vorab ermittelten Positionen hin? Dann müsste ich ja quasi in MyCompare so 'ne Art Swap für den Vertausch der zu Index1 und Index2 gehörenden Positionsangaben machen.
zu 3: Prinzipiell hast Du recht, eigentlich kann von "draussen" keiner an die Funktion ran, nur weitere Klassen innerhalb der gleichen
Unit könnten Probleme bekommen. An dem Typecast selbst komme ich aber wohl nicht vorbei.
Momentan sieht das dann jetzt so aus:
Delphi-Quellcode:
type
rPosData = record
StartPos : Word;
NextPos : Word;
end;
arPosData = Array of rPosData;
type
tSortStringList = class(TStringList)
private
fSortColumn : Integer;
fPosData : arPosData;
protected
function GetStartPos(s : String; Delimiter : Char; SortColumn : Integer) : Integer;
function GetNextPos(s : String; Delimiter : Char; iStartPos : Integer) : Integer;
public
procedure Compare;
published
property SortColumn : Integer Read FSortColumn Write fSortColumn Default 0;
end;
.
.
.
implementation
.
.
.
// Stelle im String ermitteln, ab der sortiert werden soll.
Function TSortStringList.GetStartPos(s : String; Delimiter : Char; SortColumn : Integer) : Integer;
Var
iPos : Integer;
iCount : Integer;
begin
iPos := 0;
for iCount := 1 to SortColumn Do iPos := PosEx(Delimiter,s,iPos + 1);
Inc(iPos);
Result := iPos;
end;
// Länge des zu sortierenden Strings ermitteln.
Function TSortStringList.GetNextPos(s : String; Delimiter : Char; iStartPos : Integer) : Integer;
Var
iNextPos : Integer;
begin
iNextPos := PosEx(Delimiter,s,iStartPos);
case iNextPos of 0 : iNextPos := Length(s); end;
Result := iNextPos;
end;
function MyCompare(List: TStringList; Index1, Index2: Integer): Integer;
var
iPos : Integer;
begin
with List As TSortStringList do begin
if List.CaseSensitive then begin
Result := AnsiCompareStr(Copy(List[Index1],
fPosData[Index1].StartPos,
fPosData[Index1].NextPos),
Copy(List[Index2],
fPosData[Index2].StartPos,
fPosData[Index2].NextPos)
);
end else begin
Result := AnsiCompareText(Copy(List[Index1],
fPosData[Index1].StartPos,
fPosData[Index1].NextPos),
Copy(List[Index2],
fPosData[Index2].StartPos,
fPosData[Index2].NextPos)
);
end;
case Result of
0 : ; // hier brauchen wir nichts tuten, beide String sind gleich
else
iPos := fPosData[Index1].StartPos;
fPosData[Index1].StartPos := fPosData[Index2].StartPos;
fPosData[Index2].StartPos := iPos;
iPos := fPosData[Index1].NextPos;
fPosData[Index1].NextPos := fPosData[Index2].NextPos;
fPosData[Index2].NextPos := iPos;
end;
end;
end;
procedure TSortStringList.Compare;
Var
i : Integer;
iPos : Integer;
iPosLast : Integer;
begin
SetLength(fPosData,Self.Count);
for i := 0 To Self.Count - 1 Do begin
iPos := GetStartPos(Self[i],Self.Delimiter,fSortColumn);
iPosLast := GetNextPos(Self[i],Self.Delimiter,iPos);
fPosData[i].StartPos := iPos;
fPosData[i].NextPos := iPosLast;
end;
Self.CustomSort(MyCompare);
end;
// Aufruf im Programm
procedure TForm1.Button1Click(Sender: TObject);
Var
StringListe : TSortStringList;
begin
Stringliste := TSortStringList.Create;
Stringliste.LoadFromFile('20081010.log');
Stringliste.Delimiter := '|';
Stringliste.SortColumn := 1;
Stringliste.CaseSensitive := false;
Stringliste.Compare;
StringListe.SaveToFile('20081010.log.Sort');
Stringliste.Free;
end;
Geschwindigkeitstechnisch kann ich bei den kleinen Dateien, die ich momentan habe, keinen Unterschied merken, aber bei großen Mengen dürfte das schon was ausmachen.
Vielen Dank für Deine Ideen und Anregungen.