Autor Beitrag
Airtrox
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 109


Delphi 7
BeitragVerfasst: Di 22.09.09 12:54 
hey

ich habe wieder mal eine frage:
Ich möchte ein einfaches programm, das nur ein Memo enthällt, in dem die Zeilen ab einer bestimmten Position geordnet werden sollen. Also sollte aus so einer stringlist
asdhj_asd
8ejdu_bdf
a84jd_kkk
erst ab dem Unterstrich sortiert werden. Soweit sogut, das Problem ist nur, dass die zeichen vorher erhalten bleiben sollen.
Ich habe mir gedacht, dass ich in einer schleife erst alles vornedran lösche und seperat speichere und gleichzeitig am ende der zeile eine Nummer oder was anderes setze, sodass ich die gespeicherten zeichen von vorne später wieder zuweisen kann, nachdem sie sortiert wurden.
In der Praxis halte ich diese Idee jedoch nicht für so gut, wollte deshalb mal eure Vorschläge hören.

lg
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Di 22.09.09 13:17 
Berücksichtige doch in der Vergleichsroutine einfach nur das, was nach dem Unterstrich kommt. Such ihn mit pos und kopiere dir den Rest mit copy raus.
Airtrox Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 109


Delphi 7
BeitragVerfasst: Di 22.09.09 13:27 
das war ja auch meine idee, das problem ist aber, dass ich erstmal alles ab dem Unterstrich kopieren müsste (in einen neuen String), dannn mit sort() sortieren und als ausgabe soll wieder die ganze Zeile da stehen, jedoch geordnet ab dem _
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 22.09.09 13:27 
Moin!

Wenn du nur wenige Einträge in dem Memo hast, ist der Vorschlag von user profile iconLuckie völlig OK.

Wenn es sehr viele Zeilen sind, Ansatz:
  • Mach eine temporäre Stringliste auf, z.B. var SL: TStringList;
  • Geh das Memo durch und lege den zu sortierenden Teil der Zeilen in der Stringliste ab, dabei beim Anfügen in dem .Objects[] des Eintrags den aktuellen Index ablegen :arrow: jetzt steht in der Stringliste der Teil, der Sortiert werden soll und im zugehörigen .Objects[] die Zeile, aus der der Text stammt
  • Die Stringliste sortieren: SL.Sort; (dabei werden die Objects mit getauscht)
  • Jetzt die Stringliste durchgehen und die Indizes auf das Memo übertragen:
    ausblenden Delphi-Quelltext
    1:
    2:
    for i := 0 to SL.Count-1 do
      Memo1.Lines.Objects[Integer(SL.Objects[i])] := Pointer(i);
  • Anschließend das Memo nach den .Lines.Objects[] custom-sortieren - fertig.
cu
Narses

//EDIT:
user profile iconAirtrox hat folgendes geschrieben Zum zitierten Posting springen:
das war ja auch meine idee, das problem ist aber, dass ich erstmal alles ab dem Unterstrich kopieren müsste (in einen neuen String), dannn mit sort() sortieren und als ausgabe soll wieder die ganze Zeile da stehen, jedoch geordnet ab dem _
Ich schätze mal user profile iconLuckie meinte, du solltest eine Vergleichsfunktion für .CustomSort schreiben, die das gewünschte Vergleichsresultat "on-the-fly" bestimmt. :idea:

_________________
There are 10 types of people - those who understand binary and those who don´t.
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Di 22.09.09 13:46 
user profile iconNarses hat folgendes geschrieben Zum zitierten Posting springen:

//EDIT:
user profile iconAirtrox hat folgendes geschrieben Zum zitierten Posting springen:
das war ja auch meine idee, das problem ist aber, dass ich erstmal alles ab dem Unterstrich kopieren müsste (in einen neuen String), dannn mit sort() sortieren und als ausgabe soll wieder die ganze Zeile da stehen, jedoch geordnet ab dem _
Ich schätze mal user profile iconLuckie meinte, du solltest eine Vergleichsfunktion für .CustomSort schreiben, die das gewünschte Vergleichsresultat "on-the-fly" bestimmt. :idea:

Richtig. Bei Bubblesort zum Beispiel wird eben nicht der ganze String verglichen, sondern nur der Teil, der interessiert.
Airtrox Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 109


Delphi 7
BeitragVerfasst: Di 22.09.09 14:39 
Hey,

danke für den Vorschlag, ich verstehe das auch soweit, nur bei diese Zeile bin ich etwas ratlos:
Zitat:
Geh das Memo durch und lege den zu sortierenden Teil der Zeilen in der Stringliste ab, dabei beim Anfügen in dem .Objects[] des Eintrags den aktuellen Index ablegen :arrow: jetzt steht in der Stringliste der Teil, der Sortiert werden soll und im zugehörigen .Objects[] die Zeile, aus der der Text stammt

Könntest du das etwas genauer erläutern, evt. mit einem Beispiel?

lg
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 22.09.09 15:18 
Moin!

user profile iconAirtrox hat folgendes geschrieben Zum zitierten Posting springen:
Könntest du das etwas genauer erläutern, evt. mit einem Beispiel?
ausblenden Delphi-Quelltext
1:
2:
for i := 0 to Memo1.Lines.Count-1 do
  SL.AddObject(Copy(Memo1.Lines.Strings[i],5,4),Pointer(i));
Das Markierte ist natürlich entspreched anzupassen, je nach dem, welchen Teil der Strings du extrahieren willst. :idea: ;)

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
Dude566
ontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic starofftopic star
Beiträge: 1592
Erhaltene Danke: 79

W8, W7 (Chrome, FF, IE)
Delphi XE2 Pro, Eclipse Juno, VS2012
BeitragVerfasst: Di 22.09.09 17:15 
user profile iconAirtrox hat folgendes geschrieben Zum zitierten Posting springen:
das war ja auch meine idee, das problem ist aber, dass ich erstmal alles ab dem Unterstrich kopieren müsste (in einen neuen String), dannn mit sort() sortieren und als ausgabe soll wieder die ganze Zeile da stehen, jedoch geordnet ab dem _


Und wo ist das Problem beide nach dem Sortieren wieder zu einem zu vereinen?

_________________
Es gibt 10 Gruppen von Menschen: diejenigen, die das Binärsystem verstehen, und die anderen.
Airtrox Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 109


Delphi 7
BeitragVerfasst: Di 22.09.09 19:23 
An Narses:
Wird dabei in die Stringlist also nur der Teil ab Position 5 (in deinem Bsp) kopiert? Und dann eben mit SL.sort sortiert?

Dann noch eine kleine Frage: Wenn also der die Stringlist sortiert ist, wie hänge ich den ersten Teil den Sortierten Zeilen wieder hinzu? Verstehe das noch nicht so ganz :?
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 22.09.09 19:24 
Moin!

user profile iconAirtrox hat folgendes geschrieben Zum zitierten Posting springen:
Ich möchte ein einfaches programm, das nur ein Memo enthällt, in dem die Zeilen ab einer bestimmten Position geordnet werden sollen. Also sollte aus so einer stringlist
asdhj_asd
8ejdu_bdf
a84jd_kkk
erst ab dem Unterstrich sortiert werden. Soweit sogut, das Problem ist nur, dass die zeichen vorher erhalten bleiben sollen.
Also wenn ich mir das alles nochmal durch den Kopf gehen lasse, dann sind die ganzen Ansätze für den Eimer, weil hier mal wieder die GUI als Datenlager missbraucht wird. :? Offensichtlich handelt es sich bei den Memo-Zeilen um eine kombinierte Ausgabe verschiedener Werte. Warum also das Pferd von Hinten aufzäumen, wenn man das auch gleich richtig machen kann: ;)
  • Die Werte getrennt speichern, z.B. in einer TList, die records verwaltet oder gleich in einer TObjectList, die passende Objekte verwaltet
  • Den Container sortieren (also die TList bzw. TObjectList)
  • Dann die Ausgabe im Memo durch Ersetzen des Inhalts neu erzeugen
cu
Narses

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


Delphi 7
BeitragVerfasst: Di 22.09.09 21:42 
user profile iconNarses hat folgendes geschrieben Zum zitierten Posting springen:
Moin!
  • Die Werte getrennt speichern, z.B. in einer TList, die records verwaltet oder gleich in einer TObjectList, die passende Objekte verwaltet
  • Den Container sortieren (also die TList bzw. TObjectList)
  • Dann die Ausgabe im Memo durch Ersetzen des Inhalts neu erzeugen

Da hörts bei mir auf^^ Punkt2 sollte mit SL.sort ja klappen, Punkt3 ist auch klar (neu zuweisen), aber bei dem Rest wäre ich ratlos, wie ich das hinbekommen könnte...
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 22.09.09 22:25 
Moin!

Dann hier mal ein Beispiel: ;)
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:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
type
  TElement = class(TObject)
  private
    FStr1: String;
    FStr2: String;
    function GetAsStr: String;
  public
    constructor Create(const S1, S2: String);
    property Str1: String read FStr1 write FStr1;
    property Str2: String read FStr2 write FStr2;
    property AsStr: String read GetAsStr;
  end;

  TForm1 = class(TForm)
    Memo1: TMemo;
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    ElementList: TObjectList;
  end;

//...

constructor TElement.Create(const S1, S2: String);
begin
  inherited Create;
  FStr1 := S1;
  FStr2 := S2;
end;

function TElement.GetAsStr: String;
begin
  Result := FStr1+'_'+FStr2;
end;

function MyCompare(Item1, Item2: Pointer): Integer;
begin
  Result := CompareStr(TElement(Item1).Str2,TElement(Item2).Str2);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Randomize;
  ElementList := TObjectList.Create;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  ElementList.Free;
end;

procedure TForm1.Button1Click(Sender: TObject);
  var
    i: Integer;

  function RandStr(const Len: Integer): String;
    var
      i: Integer;
  begin
    SetLength(Result,Len);
    for i := 1 to Len do
      Result[i] := Char(Random(26)+Ord('A'));
  end;

begin
  ElementList.Clear;
  // ein paar Elemente anlegen
  for i := 1 to Random(10)+2 do
    ElementList.Add(TElement.Create(RandStr(5),RandStr(8)));
  ElementList.Sort(MyCompare);
  // Ausgeben
  Memo1.Clear;
  for i := 0 to ElementList.Count-1 do
    Memo1.Lines.Add(TElement(ElementList.Items[i]).AsStr);
end;
cu
Narses

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


Delphi 7
BeitragVerfasst: Mi 23.09.09 13:04 
Dabei bekomme ich die Fehlermeldung:
Screenshot

die unit Contnrs hab ich miteingebunden.

Moderiert von user profile iconNarses: Bild als Anhang hochgeladen.
Einloggen, um Attachments anzusehen!
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 23.09.09 13:14 
Moin!

Ähm :? das ist kein c&p-Code, etwas Anpassung von dir auf dein Projekt muss ich schon erwarten können... :|

cu
Narses

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


Delphi 7
BeitragVerfasst: Mi 23.09.09 13:35 
Da hast du absolut Recht, aber ich muss ehrlich sagen, dass ich den Quelltext sogut wie gar nicht bzw. nur in kleinen Teilen verstehe, deshalb wüsste ich auch nicht wirklich wo ich es eben anpassen muss :(
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 23.09.09 13:59 
Moin!

user profile iconAirtrox hat folgendes geschrieben Zum zitierten Posting springen:
ich muss ehrlich sagen, dass ich den Quelltext sogut wie gar nicht bzw. nur in kleinen Teilen verstehe, deshalb wüsste ich auch nicht wirklich wo ich es eben anpassen muss :(
OK, dann noch etwas ausführlicher. ;)

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:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
type
  // das ist ein Element deiner Datenmenge, z.Zt. hat es nur 2 Strings
  TElement = class(TObject)
  private
    FStr1: String;
    FStr2: String;
    function GetAsStr: String;
  public
    constructor Create(const S1, S2: String); // Element anlegen, dabei direkt die Strings eintragen
    property Str1: String read FStr1 write FStr1;
    property Str2: String read FStr2 write FStr2;
    property AsStr: String read GetAsStr; // die Strings mit "_" verkettet abliefern
  end;

  // die Test-Formularklasse - hier nur dazu da, damit du siehst, wo welche Anpassungen hin müssen
  TForm1 = class(TForm)
    Memo1: TMemo; // Memo für die AUsgabe
    Button1: TButton; // Button für Funktionstest
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    ElementList: TObjectList; // da werden die Elemente gespeichert
  end;

//...

// Konstruktor der Element-Klasse
constructor TElement.Create(const S1, S2: String);
begin
  inherited Create;
  FStr1 := S1;
  FStr2 := S2;
end;

function TElement.GetAsStr: String;
begin
  Result := FStr1+'_'+FStr2;
end;

// Funktion, um zwei Elemente zu vergleichen, dabei wird der 2. String als Kriterium benutzt
function MyCompare(Item1, Item2: Pointer): Integer;
begin
  Result := CompareStr(TElement(Item1).Str2,TElement(Item2).Str2);
end;

// --- ab hier Formularklasse ---

procedure TForm1.FormCreate(Sender: TObject);
begin
  Randomize;
  ElementList := TObjectList.Create; // Container-Klasse anlegen
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  ElementList.Free; // freigeben (enthaltene Objekte werden mit freigegeben)
end;

// Test-Funktion
procedure TForm1.Button1Click(Sender: TObject);
  var
    i: Integer;

  // einen String der Länge Len mit zufälligen Buchstaben gefüllt abliefern
  function RandStr(const Len: Integer): String;
    var
      i: Integer;
  begin
    SetLength(Result,Len);
    for i := 1 to Len do
      Result[i] := Char(Random(26)+Ord('A'));
  end;

begin
  ElementList.Clear; // bisherige Elemente löschen/freigeben
  // ein paar Elemente anlegen
  for i := 1 to Random(10)+2 do
    ElementList.Add( // ein Element in die Liste einfügen
      TElement.Create( // ein neues Element anlegen
        RandStr(5), // String1 -> 5 Zeichen
        RandStr(8)  // String2 -> 8 Zeichen
      )
    );
  ElementList.Sort(MyCompare); // die Elemente sortieren, dabei zum Vergleichen die angegebene Funktion benutzen
  // Ausgeben
  Memo1.Clear;
  for i := 0 to ElementList.Count-1 do // alle Elemente
    Memo1.Lines.Add(TElement(ElementList.Items[i]).AsStr); // Ausgeben
end;
cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.