Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Sortieren eines Arrays of String (https://www.delphipraxis.net/201283-sortieren-eines-arrays-string.html)

DonPedroFo 8. Jul 2019 09:18

Delphi-Version: 5

Sortieren eines Arrays of String
 
Hallo,
ich bin hier relativ neu, und hab eine Aufgabe bekommen bei der ich momentan auf dem Schlauch stehe.

Folgendes Szenario muss ich lösen.

Ich habe eine "Textdokument" mit mehreren (98) Zeilen.
Jede Zeile beinhaltet einen Code der früher oder später in ein Flashspeicher geschrieben wird.

Eine Zeile sieht beispielsweise so aus:
S10011223344556677889900AABBCCDDEEFF (natürlich nicht in dieser "perfekten" Reihenfolge)

Code:
Eine Zeile setzt sich wie folgt zusammen:
S1 / 00 / 1122 / ..... / FF
|    |    |     |Daten
|    |    |Adresse
|    |Anzahl der Bytes
|Startcode

In diesem Fall wäre die Hexzahl "1122" die Adresse im Flashsspeicher, in die Daten geschrieben werden.
Heißt die Daten "..." müssen an die Adresse "1122" geschrieben werden.

Jede Zeile hat eine andere Adresse mit unterschiedlichen Daten.

Um den Schreibvorgang im Flashspeicher zu beschleunigen muss ich bei der Adresse "0000" anfangen zu schreiben und bei der Adresse "FFFF" aufhören.

Die Zeile sind aber durcheinander was heißt ich muss erstmal die alle Zeile sortieren im Bezug auf die Adresse
z.b.
Vor dem Sortieren
Adresse Zeile 1: S1/00/ 3853 /.....
Adresse Zeile 2: S1/00/ F325 /.....
Adresse Zeiel 3: S1/00/ 1023 /.....

Nach dem sortieren:
Adresse Zeile 3: S1/00/ 1023 /.....
Adresse Zeile 1: S1/00/ 3853 /.....
Adresse Zeile 2: S1/00/ F325 /.....

Natürlich darf ich nicht nur die Adresse berücksichtigen sondern muss die ganze Zeile "mit sortieren"

Ich hab mir schon die Sortier-Algorithmen angeschaut bin aber auf keinen grünen zweig gekommen.

PS. Jede Zeile steht in einem: Array of String

DeddyH 8. Jul 2019 09:27

AW: Sortieren eines Arrays of String
 
Ich würde mir eine entsprechende Klasse definieren, die Strings parsen und jede Instanz in eine TObjectList packen. Die kann man sortieren und anschließend von oben nach unten abarbeiten. Um Zahlen in hexadezimaler Darstellung zu sortieren musst Du sie erst in Zahlen umwandeln, das geht mit StrToInt('$' + hexadezimale Darstellung).

Luckie 8. Jul 2019 09:40

AW: Sortieren eines Arrays of String
 
Parsen und in ein Record packen. Dann kann man nach dem gewünschten Feld sortieren.

hoika 8. Jul 2019 09:42

AW: Sortieren eines Arrays of String
 
Hallo,
das kannst Du doch mit einem normalem CustomSort hinbekommen.

Whookie 8. Jul 2019 09:47

AW: Sortieren eines Arrays of String
 
Liste parsen und die Adresse im Objects[] - Feld ablegen und danach nach diesem Feld sortieren.

Delphi.Narium 8. Jul 2019 09:47

AW: Sortieren eines Arrays of String
 
Das geht mit 'ner TStringList.

Schau Dir bitte mal dashier an: https://www.delphipraxis.net/835874-post7.html

Du müsstest das dortige Beispiel für die Funktion MyCompare entsprechend Deinen Anforderungen anpassen.

DonPedroFo 8. Jul 2019 09:53

AW: Sortieren eines Arrays of String
 
Liste der Anhänge anzeigen (Anzahl: 1)
Erstmal danke für die schnelle Antwort.

Am besten ich schreib noch dazu was ich bisher gemacht habe.

- Textdatei in ein Memofeld laden
- Eine Textzeile in ein Editfeld kopieren
- Einzelne "Blöcke" in Editfelder kopieren.

siehe Bild

Der schöne Günther 8. Jul 2019 10:11

AW: Sortieren eines Arrays of String
 
Ich finde das alles etwas zu kompliziert.
Delphi-Quellcode:
TArray.Sort(..)
aus
Delphi-Quellcode:
System.Generics.Collections
bietet dir alles um ein Array zu sortieren wie du magst. Die Adresse und andere Dinge lassen sich prächtig mit regulären Ausdrucken (
Delphi-Quellcode:
System.RegularExpressions
) auslesen.

Hier ein Beispiel dass deine Strings der Adresse nach sortiert ausgibt:

Delphi-Quellcode:
program Project1;

{$APPTYPE CONSOLE}
{$R *.res}

uses
   System.SysUtils,
   System.Generics.Collections,
   System.Generics.Defaults,
   System.RegularExpressions;

type
   TAddress = Word;

   function getAddress(const line: String): TAddress;
   const
      pattern = '^S(\d)(\d){2}((\d){4}).*FF';
   var
      match: TMatch;
   begin
      match := TRegEx.Match(line, pattern);
      Result := TAddress.Parse(match.Groups[3].Value);
   end;

   procedure printLines(const lines: TArray<String>); inline;
   var
      line: String;
   begin
      for line in lines do
         WriteLn(line);
    end;

procedure p();
var
   lines: TArray<String>;
   sortByAddress: IComparer<String>;
begin
   lines := [
      'S10011223344556677889900AABBCCDDEEFF', // Adresse "1122"
      'S10010223344556677889900AABBCCDDEEFF', // Adresse "1022"
      'S10014223344556677889900AABBCCDDEEFF' // Adresse "1422"
   ];

   sortByAddress :=
      TComparer<String>.Construct(
         function(const left, right: String): Integer
         begin
            Result := getAddress(left) - getAddress(right);
         end
      );

   TArray.Sort<String>(lines, sortByAddress);
   printLines(lines);
end;

begin
   p();
   readln;
end.

Delphi.Narium 8. Jul 2019 10:15

AW: Sortieren eines Arrays of String
 
Kurz und knapp:
Delphi-Quellcode:
procedure TForm1.SortMemo;
var
        i : Integer;
        k : Integer;
        s : String;
begin
  for i := 0 to Memo1.Lines.Count - 1 do begin
    for k := i + 1 to Memo1.Lines.Count - 1 do begin
      if Copy(Memo1.Lines[k],5,4) < Copy(Memo1.Lines[i],5,4) then begin
        s := Memo1.Lines[i];
        Memo1.Lines[i] := Memo1.Lines[k];
        Memo1.Lines[k] := s;
      end;
    end;
  end;
end;

hoika 8. Jul 2019 11:01

AW: Sortieren eines Arrays of String
 
Hallo,
Memo1.BeginUpdate/EndUpdate nicht vergessen.

DonPedroFo 8. Jul 2019 12:40

AW: Sortieren eines Arrays of String
 
Vielen Dank für die zahlreichen Antworten. Das hilf mir enorm weiter.
@Delphi.Narium
deine Lösung finde ich am plausibelsten. Da kann ich auch nachvollziehen was im Hintergrund abläuft.

Vielen Dank manchmal scheint mir es am Ende einfacher als es am Anfang aussieht.

Mavarik 8. Jul 2019 15:13

AW: Sortieren eines Arrays of String
 
Zitat:

Zitat von DonPedroFo (Beitrag 1436290)
@Delphi.Narium
deine Lösung finde ich am plausibelsten. Da kann ich auch nachvollziehen was im Hintergrund abläuft.

Wenn es Dir nicht auf die Geschwindigkeit ankommt, kannst Du den BubbleSort von Delphi.Narium nehmen, schneller ist natürlich der Ansatz vom schönen Günter... ggf. einfach mit einem String vergleich und nicht per RegEx!

Mavarik

Andreas13 8. Jul 2019 15:53

AW: Sortieren eines Arrays of String
 
Hallo,
wenn es jetzt schon um die Sortiergeschwindigkeit geht (wir reden hierbei nicht unbedingt nur über die zu sortierenden 98 Datensätzen), dann möchte ich auch meinen „Senf“ dazu geben und einen vollkommen anderen Ansatz zeigen. Zunächst möchte jedoch auch ich feststellen, daß
a):
die Lösung von Der schöne Günther sehr professionell & komplex ist und viel Know-how enthält und voraussetzt.
b):
die Lösung von Delphi.Narium sehr kompakt, verständlich und elegant ist und sortiert direkt im Memo.

Mein Ansatz sieht wie folgt aus: Da DonPedroFo die „Adressen“ bereits aus seinen Stringzeilen extrahiert hat, könnte er (wenn er Zeit & Lust zum Experimentieren hat) folgendes machen:
1):
Die extrahierten „Adressen“ in einen IntegerVektor (= Array of Integer) packen,
2):
Die kompletten Original-Strings (unverändert) in einen StringVektor (= Array of String) laden.

Ich habe vor längerer Zeit eine Routine zum MIT-Sortieren von gekoppelten Extended- und Integer-Vektoren (= Arrays) entwickelt, dessen Code unten folgt. Der MasterVektor wird hierbei sortiert, der Rest (in der Routine 3 weitere Vektoren) erfährt aber dieselben Tauschaktionen, wird also quasi mitsortiert.
In DonPedroFo's Fall wäre der zu sortietrende IntegerVektor der MasterVektor. Der StringVektor wird ohne Vergleichsoperationen nur "mitbewegt". Mit geringem Aufwand lässt sich meine Routine anpassen. Gegebenenfalls kann man die überflüssigen Vektoren löschen oder einfach den NILVektor-DummyParameter übergeben.
Delphi-Quellcode:
Type
  TDynExtendedVektor = TArray<Extended>; // = Array of Extended;
  TDynIntegerVektor = TArray<Integer>; // Array of Integer;


(* Krücken: sie sollten eigentlich CONSTANT sein: es geht aber NICHT! *)
VAR
  NILVektor_Extended: TDynExtendedVektor;
  NILVektor_Integer : TDynIntegerVektor;
 (* Eigentlich Krücken: sie sollten eigentlich CONSTANT sein: es geht aber NICHT!
  Solange Länge NICHT gesetzt wird, ist es ein NIL-Vektor bzw. eine NIL-Matrix *)



Procedure MIT_Sort_Extended_Vektor_byQuick(VAR A_Vektor_MASTER: TDynExtendedVektor;
                                                  VAR B_Vektor: TDynExtendedVektor;
                                                  VAR C_Vektor: TDynExtendedVektor;
                                                  VAR I_Vektor: TDynIntegerVektor;
                                                   Aufsteigend: Boolean = True);

// Angepasst nach Easy Delphi Helper's QuickSort für Integer_Vektor; Rekursiv --> STACK!!
// Zum MIT_Sortieren zugehöriger Vektoren
// QuickSort ist ein rekursives (STACK!!!), instabliles (!!) Sortierverfahren,
// Problematisch ist, wenn zwei Einträge genau gleich sind
//
// beim Fehlen eines Vektors, als Parameter folgende Dummys übergeben:
// NILVektor_Extended: TDynExtendedVektor;
// NILVektor_Integer : TDynIntegerVektor;

  Procedure Quick_Sort(Var a: TDynExtendedVektor; VAR b: TDynExtendedVektor;
                       VAR c: TDynExtendedVektor; VAR iV: TDynIntegerVektor; iLo, iHi: Integer);

  var
    Lo, Hi : Integer;
    Mid, T : Extended;
    T_B, T_C: Extended;
    T_i    : Integer;

  Begin
    Lo := iLo;
    Hi := iHi;
    Mid:= a[(Lo + Hi) div 2];
    Repeat
      While a[Lo] < Mid Do
        Inc(Lo);

      While a[Hi] > Mid Do
        dec(Hi);

      IF Lo <= Hi Then Begin // ALLE Vertauschungen sind HIER:
        // A:
        T   := a[Lo];
        a[Lo]:= a[Hi];
        a[Hi]:= T;

        // B:
        IF b <> NIL Then Begin
          // NIL lässt sich NICHT DIREKT als Paramter für den Vektor übergeben, nur über einen Dummy-Vektor: NILVektor_Extended oder NILVektor_Integer
          T_B := b[Lo];
          b[Lo]:= b[Hi];
          b[Hi]:= T_B;
        End;

        // C:
        IF c <> NIL Then Begin
          // NIL lässt sich NICHT DIREKT als Paramter für den Vektor übergeben, nur über einen Dummy-Vektor: NILVektor_Extended oder NILVektor_Integer
          T_C := c[Lo];
          c[Lo]:= c[Hi];
          c[Hi]:= T_C;
        End;

        // iV:
        IF iV <> NIL Then Begin
          // NIL lässt sich NICHT DIREKT als Paramter für den Vektor übergeben, nur über einen Dummy-Vektor: NILVektor_Extended oder NILVektor_Integer
          T_i  := iV[Lo];
          iV[Lo]:= iV[Hi];
          iV[Hi]:= T_i;
        End;

        Inc(Lo);
        dec(Hi);
      End;
    Until Lo > Hi;

    IF Hi > iLo Then
      Quick_Sort(A_Vektor_MASTER, B_Vektor, C_Vektor, I_Vektor, iLo, Hi);

    IF Lo < iHi Then
      Quick_Sort(A_Vektor_MASTER, B_Vektor, C_Vektor, I_Vektor, Lo, iHi);
  End;

Begin
  // Rekursiver Aufruf:
  Quick_Sort(A_Vektor_MASTER, B_Vektor, C_Vektor, I_Vektor, Low(A_Vektor_MASTER), High(A_Vektor_MASTER));

  IF Aufsteigend Then
    Exit;

  // Absteigend: -> Krücke: Umkopieren!
  Vektor_Umsortieren(A_Vektor_MASTER, B_Vektor, C_Vektor, I_Vektor);
End;{MIT_Sort_Extended_Vektor_byQuick}
{------------------------------------}

Procedure Vektor_Umsortieren(VAR A_Vektor: TDynExtendedVektor;
                             VAR B_Vektor: TDynExtendedVektor;
                             VAR C_Vektor: TDynExtendedVektor;
                             VAR I_Vektor: TDynIntegerVektor); overload;

// Dreht die Sortierfolge durch Umkopieren um: Aufsteigend --> Absteigend bzw. Absteigend --> Aufsteigend
// ist nur eine Krücke, Doch der Aufwand, direkt Absteigend zu sortieren ist viel größer...
// beim Fehlen eines Vektors, als Parameter folgrnde Dummys übergeben:
// NILVektor_Extended: TDynExtendedVektor;
// NILVektor_Integer : TDynIntegerVektor;

VAR
  i, j, tmp_i       : Integer;
  tmp_A, tmp_B, tmp_C: Extended;

Begin
  j:= High(A_Vektor);

Begin
  For i:= Low(A_Vektor) To (High(A_Vektor) div 2) Do Begin
    // A:
    tmp_A     := A_Vektor[i];
    A_Vektor[i]:= A_Vektor[j];
    A_Vektor[j]:= tmp_A;

    // B:
    IF B_Vektor <> NIL Then Begin
      // NIL lässt sich NICHT DIREKT als Paramter für den Vektor übergeben, nur über einen Dummy-Vektor: NILVektor_Extended oder NILVektor_Integer
      tmp_B     := B_Vektor[i];
      B_Vektor[i]:= B_Vektor[j];
      B_Vektor[j]:= tmp_B;
    End;

    // C:
    IF C_Vektor <> NIL Then Begin
      // NIL lässt sich NICHT DIREKT als Paramter für den Vektor übergeben, nur über einen Dummy-Vektor: NILVektor_Extended oder NILVektor_Integer
      tmp_C     := C_Vektor[i];
      C_Vektor[i]:= C_Vektor[j];
      C_Vektor[j]:= tmp_C;
    End;

    // Integer:
    IF I_Vektor <> NIL Then Begin
      // NIL lässt sich NICHT DIREKT als Paramter für den Vektor übergeben, nur über einen Dummy-Vektor: NILVektor_Extended oder NILVektor_Integer
      tmp_i     := I_Vektor[i];
      I_Vektor[i]:= I_Vektor[j];
      I_Vektor[j]:= tmp_i;
    End;

    dec(j);
  End;
End;{Vektor_Umsortieren}
{----------------------}
Vielleicht hilft es jemandem in ähnlichen Aufgabenstellungen weiter.
Gruß
Andreas

DeddyH 8. Jul 2019 16:51

AW: Sortieren eines Arrays of String
 
Falls die Angabe "Delphi 5" tatsächlich stimmt, lösen sich alle generischen Lösungen in Rauch auf, daher hatte ich mir das vorsichtshalber verkniffen.

samso 8. Jul 2019 19:50

AW: Sortieren eines Arrays of String
 
Warum soll das erst sortiert werden? Da ja am Ende die Daten sowieso in das Flash geschrieben werden sollen, kannst Du auch direkt eine Kopie der Flashdaten im RAM anlegen. Du reservierst die 64 Kilobyte und kopierst dann die Daten direkt nachdem du zwei Hexziffern zu einem Byte konvertiert hast an die richtige Stelle in das 64 Kilobyte-Array. Die Adresse wo das hin muss hast Du ja. Danach kannst Du das komplette Byte-Array, so wie es ist in den Flash-Speicher kopieren.

p80286 8. Jul 2019 21:04

AW: Sortieren eines Arrays of String
 
Keine schlechte Idee, dann wäre es allerdings auch sinnvoll die Daten gleich auf Konsiztenz zu prüfen. Es könnte doch peinlich sein, wenn es Löcher oder Überschneidungen gäbe.

Gruß
K-H

DonPedroFo 10. Jul 2019 08:50

AW: Sortieren eines Arrays of String
 
Die Angabe Delphi 5 stimmt :D

Ich komme mit der kurzen Variante von Delphi.Narium gut zurecht.
Im großen und ganzen hätte ich da bestimmt auch selber drauf kommen können.
Aber trotzdem vielen Dank. Die nächste Frage lauert schon in meinem Kopf. Lang dauert es nicht mehr bis ich sie stelle.

DonPedroFo 10. Jul 2019 12:07

AW: Sortieren eines Arrays of String
 
Ich weiß nicht ob ich die Frage hier anhängen kann oder ob ich einen neuen Thread auf machen sollte.

Es geht um folgendes:

Da ich unterschiedlich lange Datenfelder habe, hab ich die einzelnen Längen von jedem String bzw. die Länge vom Längsten String ermittelt und "gespeichert".

Zum späteren programmieren müssen alle Strings im Datenfeld eine Bestimmte Länge haben z.b.

Vorher:
S01122334455666
S0112233
S01144
S011

Nachher:
S0112233445566
S0112233FFFFFF
S01144FFFFFFFF
S011FFFFFFFFFF

Was ich damit sagen will ist, das ich die Länge vom längsten String als Referenzlänge nehme und alle Strings die kleiner sind mit "F" auffülle bis sie die gewünschte länge haben.

Ich hab das ganze schon mit FillChar(Datenfeld,Sizeof(XX),X);

Wie kann ich hier eine Länge bzw. "F" angeben?

Andreas13 10. Jul 2019 12:52

AW: Sortieren eines Arrays of String
 
Verscuh es mal mit der Funktion System.WideString.StringOfChar(WideChar ch, int count):
Delphi-Quellcode:
// ungetestet:
String_Lang:= String_kurz + StringOfChar('F', Len_Soll - Length(String_kurz));
Gruß
Andreas

DeddyH 10. Jul 2019 13:39

AW: Sortieren eines Arrays of String
 
In Delphi 5 war die IIRC in SysUtils, wenn es sie überhaupt schon gab.

Andreas13 10. Jul 2019 14:24

AW: Sortieren eines Arrays of String
 
Zitat:

Zitat von DeddyH (Beitrag 1436428)
In Delphi 5 war die IIRC in SysUtils, wenn es sie überhaupt schon gab.

In diesem Fall hast Du hier eine selbstgestrickte, nicht so optimierte Lösung:
Delphi-Quellcode:
Function MyStringOfChar(Ch: Char; Count: Integer): String;
Var
  i: Integer;
  S: String;
   
Begin
  S:= '';
  For i:= 1 To Count Do
    S:= S + Ch;

  Result:= S;
End;
Gruß, Andreas

Dalai 10. Jul 2019 14:38

AW: Sortieren eines Arrays of String
 
StringOfChar gibt es in Delphi 5, offensichtlich integriert im Compiler (die Hilfe sagt Unit System, die Funktion ist dort aber nicht zu finden).

Grüße
Dalai

Andreas13 10. Jul 2019 15:01

AW: Sortieren eines Arrays of String
 
DonPedroFo könnte - falls Delphi 5 diese Funktion schon kennt - auch direkt die Funktion
Delphi-Quellcode:
PadRight(TotalWidth: Integer; PaddingChar: Char): string;
verwenden. In XE5 ist sie zu finden in der Unit System.SysUtils.
Gruß, Andreas

Andreas13 10. Jul 2019 15:14

AW: Sortieren eines Arrays of String
 
Vermutlich gibt es die Funktion PadRight(..) in Delphi 5 noch nicht. DonPedroFo könnte jedoch wie folgt vorgehen:
Delphi-Quellcode:
function MyPadRight(Str_kurz: String; Ch: Char; Len_Soll: Integer): String;
var
  n_Ch: Integer;
 
begin
  Result:= Str_kurz;
  n_Ch:= Len_Soll - Length(Str_kurz);
  If n_Ch < 1 Then
    Exit;
   
  Result:= Str_kurz + StringOfChar(Ch, n_Ch); // oder MyStringOfChar(..) von oben
end;

Delphi.Narium 10. Jul 2019 17:39

AW: Sortieren eines Arrays of String
 
Sortierroutine von oben etwas angepasst:
Delphi-Quellcode:
const
  csFFFF = 'FFFFFFFFFFFFFF'; // Soviele F, wie maximal benötigt werden könnten.
  ciFFFF = 14; // Maximale Anzahl von F, die benötigt werden kann.

function FillFFFF(s : String) : String;
begin
  Result := s + Copy(csFFFF,1,ciFFFF - Length(s));
end;

procedure TForm1.SortMemo;
var
        i : Integer;
        k : Integer;
        s : String;
begin
  Memo1.BeginUpdate;
  // Zuerst alles mit F auf Pflichtlänge auffüllen
  for i := 0 to Memo1.Lines.Count - 1 do Memo1.Lines[i] := FillFFFF(Memo1.Lines[i]);
  // und dann sortieren.
  for i := 0 to Memo1.Lines.Count - 1 do begin
    for k := i + 1 to Memo1.Lines.Count - 1 do begin
      if Copy(Memo1.Lines[k],5,4) < Copy(Memo1.Lines[i],5,4) then begin
        s := Memo1.Lines[i];
        Memo1.Lines[i] := Memo1.Lines[k];
        Memo1.Lines[k] := s;
      end;
    end;
  end;
  Memo1.EndUpdate;
end;

DonPedroFo 11. Jul 2019 08:04

AW: Sortieren eines Arrays of String
 
Wahnsinn es Funktioniert auf anhieb.

Vielen Dank. Sowas nenn ich mal nützliche Hilfe.

DonPedroFo 11. Jul 2019 11:38

AW: Sortieren eines Arrays of String
 
@Delphi.Narium
Die Lösung ist schonmal perfekt.

Könnte ich, um das ganze etwas variabler zu schreiben,
die Zeilen

csFFFF = 'FFFFFFFFFFFFFF';
ciFFFF = 14;

irgendwie so schreiben

csFFFF = (Variable)'F'
ciFFFf = (Variable)

wenn als Variable z.b. 10 steht

csFFFF = 'FFFFFFFFFF' //10xF
ciFFFF = 10

Delphi.Narium 11. Jul 2019 12:14

AW: Sortieren eines Arrays of String
 
Sortierroutine von oben etwas angepasst:
Delphi-Quellcode:

function Filler(s : String; sFillChar : Char; iLength : Integer) : String;
begin
  Result := s + Copy(DupeString(sFillChar, iLength), 1, iLength - Length(s));
end;

procedure TForm1.SortMemo;
var
        i : Integer;
        k : Integer;
        s : String;
begin
  Memo1.BeginUpdate;
  // Zuerst alles mit auf Pflichtlänge auffüllen
  for i := 0 to Memo1.Lines.Count - 1 do Memo1.Lines[i] := Filler(Memo1.Lines[i],'F',14);
  // und dann sortieren.
  for i := 0 to Memo1.Lines.Count - 1 do begin
    for k := i + 1 to Memo1.Lines.Count - 1 do begin
      if Copy(Memo1.Lines[k],5,4) < Copy(Memo1.Lines[i],5,4) then begin
        s := Memo1.Lines[i];
        Memo1.Lines[i] := Memo1.Lines[k];
        Memo1.Lines[k] := s;
      end;
    end;
  end;
  Memo1.EndUpdate;
end;
Wenn's noch flexibler sein soll, da bau ins Formular noch zwei Edits ein, z. B.: edFillChar für das Zeichen, mit dem aufgefüllt werden soll und edLineLength für die Länge, bis zu der die einzelnen Zeilen aufgefüllt werden sollen.
Delphi-Quellcode:
function Filler(s : String; sFillChar : Char; iLength : Integer) : String;
begin
  Result := s + Copy(DupeString(sFillChar, iLength), 1, iLength - Length(s));
end;

procedure TForm1.SortMemo;
var
        i : Integer;
        k : Integer;
        s : String;
        iLength : Integer;
        sFillChar : Char;
begin
  Memo1.BeginUpdate;
  iLength := StrToInt(Trim(edLineLength.Text));
  sFillChar := Copy(edFillChar.Text,1,1);
  // Zuerst alles mit auf Pflichtlänge auffüllen
  for i := 0 to Memo1.Lines.Count - 1 do Memo1.Lines[i] := Filler(Memo1.Lines[i],sFillChar,iLength);
  // und dann sortieren.
  for i := 0 to Memo1.Lines.Count - 1 do begin
    for k := i + 1 to Memo1.Lines.Count - 1 do begin
      if Copy(Memo1.Lines[k],5,4) < Copy(Memo1.Lines[i],5,4) then begin
        s := Memo1.Lines[i];
        Memo1.Lines[i] := Memo1.Lines[k];
        Memo1.Lines[k] := s;
      end;
    end;
  end;
  Memo1.EndUpdate;
end;
Falls Delphi 5 die Funktion DupeString noch nicht kennen sollte:
Delphi-Quellcode:
function DupeString(sZeichen : String; iAnzahl : Integer) : String;
var
  i : Integer;
begin
  Result := '';
  for i := 1 to iAnzahl do Result := Result + sZeichen;
end;

DonPedroFo 11. Jul 2019 13:02

AW: Sortieren eines Arrays of String
 
Jetzt bekomme ich "Nicht genügend wrikliche Parameter" an dieser Stelle

Musste die Function DubString noch erstellen da sie Delphi 5 anscheinend nicht hat

Result := s + Copy(DupeString(sFillChar, iLength), iLength - Length(s));

Delphi.Narium 11. Jul 2019 13:23

AW: Sortieren eines Arrays of String
 
Da fehlt 'ne 1,

Hab's oben ergänzt.

Michael II 12. Jul 2019 10:40

AW: Sortieren eines Arrays of String
 
Wie erwähnt wurde, müsste man hier ja nicht sortieren.

Wenn doch: Eventuell möchten Frau oder Mann ja später irgendwann einmal grössere Arrays sortieren. Und da ist die Verwendung von TMemo.Lines sehr bald sehr langsam (auch mit ..BeginUpdate, ..EndUpdate).

Auf meiner Kiste für 1000 Elemente. Sortieren über TMemo.Lines ~1200ms, Code unten: ~5ms (maximal "unsortiert"). Bei 5000 Elementen: Sortieren über TMemo.Lines ~32sec, Code unten: ~15ms (wenn bereits sortiert) ~60ms ("maximal "unsortiert")

Du kannst dabei TStringList.Sort fürs Sortieren verwenden (oder auch deinen Bubble Code). Sort ist natürlich etwas schneller

Delphi-Quellcode:
var ts : TStringList;
...

// Inhalt von Memo in die StringList schreiben:
  ts.Text := memo1.Lines.Text;

// Der Teil T, nach welchem sortiert werden soll wird zusätzlich an den Anfang der zu sortierenden Strings geschrieben:
  for i := 0 to ts.Count-1 do
  begin
    hs := ts.Strings[i];
    ts.Strings[i] := Copy( hs,5,4) + hs;
  end;

// Sortieren mit Sort oder Bubble oder wie auch immer
  ts.Sort;

// T löschen
  for i := 0 to ts.Count-1 do
  begin
    hs := ts.Strings[i];
    Delete( hs, 1, 4 );
    ts.Strings[i] := hs;
  end;

// zurück schreiben:
  memo1.Lines.Text := ts.Text;

DonPedroFo 22. Jul 2019 12:03

AW: Sortieren eines Arrays of String
 
WOW..., @Michael Danke, das Sortieren mit deinem Code geht ja mal deutlich schneller

mkinzler 22. Jul 2019 12:18

AW: Sortieren eines Arrays of String
 
Man könnte auch einfach eine benutzerdefinierte Sort-Methode implementieren.

Delphi-Quellcode:
TStringList.CustomSort

Michael II 23. Jul 2019 01:56

AW: Sortieren eines Arrays of String
 
Ja du kannst natürlich auch CustomSort verwenden. CustomSort ist etwas langsamer* als die Lösung via Sort (bei 5 Mio Elementen ca. 50%), aber dafür sehr übersichtlich.

*langsamer...: Die Vergleichsfunktion v(f(list[index1]), f(list[index2]) ) in CustomCompare wird bei der Ausführung von CustomSort ca. lb(n)*n Mal aufgerufen. => Die Funktion f wird 2*lb(n)*n Mal aufgerufen. => CustomCompare berechnet für jedes der n Listenelemente l[i] den Wert f(l[i]) im Schnitt 2*lb(n) Mal (statt 1 Mal via Sort). Je komplexer die Funktion f ist, desto weniger lohnt sich (punkto Rechenaufwand) der Weg über CusomtSort.


Delphi-Quellcode:
function CustomCompare(List: TStringList; Index1, Index2: Integer): Integer;
begin
  Result := AnsiCompareText( Copy(List[index1],5,4), Copy(List[index2],5,4) );
end;

procedure TForm115.Button1Click(Sender: TObject);
var arr, hs : TStringList;
    anz, i : integer;

begin
  anz := 5000;

  arr := TStringList.Create;
  for i := 0 to anz do arr.Add(inttohex( random($FFFFFFFF), 8 ) + inttohex( random($FFFFFFFF), 8 ));

  hs := TStringList.Create;

  hs.Text := arr.Text;
  // Mit CustomSort
  hs.CustomSort( CustomCompare );

  hs.Text := arr.Text;
  // Mit Sort
  for i := 0 to anz do
    hs.Strings[i] := Copy(hs.Strings[i],5,4) + hs.Strings[i];
  hs.Sort;
  for i := 0 to anz do
    hs.Strings[i] := Copy( hs.Strings[i],5,maxint );

  hs.Free;
  arr.Free;
end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 06:55 Uhr.

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