AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

StringList Textblöcke verschieben

Ein Thema von DieDolly · begonnen am 21. Mai 2019 · letzter Beitrag vom 22. Mai 2019
Antwort Antwort
Seite 2 von 3     12 3   
DieDolly

Registriert seit: 22. Jun 2018
2.175 Beiträge
 
#11

AW: StringList Textblöcke verschieben

  Alt 22. Mai 2019, 11:45
Die Blöcke haben maximal 30 Zeilen und die Datei ist bis zu 80000 Zeilen lang.
  Mit Zitat antworten Zitat
Delphi.Narium

Registriert seit: 27. Nov 2017
2.415 Beiträge
 
Delphi 7 Professional
 
#12

AW: StringList Textblöcke verschieben

  Alt 22. Mai 2019, 11:53
Bei der Menge kann die Kombination aus Insert und Delete schon deutlich in die Laufzeit gehen.
  Mit Zitat antworten Zitat
DieDolly

Registriert seit: 22. Jun 2018
2.175 Beiträge
 
#13

AW: StringList Textblöcke verschieben

  Alt 22. Mai 2019, 11:55
Ich habe gerade das Beispiel von der vorherigen Seite getestet mit dieser Datei
Zitat:
1
2
3
4
5

6
7
8
9
10

11
12
13
14
15

Und diesem Aufruf und ich bekomme den Out of bounce Fehler
VerschiebeZeilen(sl, 5, 6, 18); // Block 5-10 soll nach 15 verschoben werden Wenn ich 0, 5, 10 eingebe, kommt das hier als Ergebnis. Scheint etwas wackelig zu sein
Zitat:
6
7
8
9
10

11
12
13
14
6
7
8
9
10

15

  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe
Online

Registriert seit: 20. Jan 2006
Ort: Lübbecke
10.980 Beiträge
 
Delphi 12 Athens
 
#14

AW: StringList Textblöcke verschieben

  Alt 22. Mai 2019, 11:57
(ungetestet hingedaddelt.)
Du musst noch beachten, daß sich durch die sl.Delete Anweisungen der effektive Wert von ATargetLine ändern kann - nämlich dann, wenn AStartLine < ATargetLine ist.

Ich könnte mir vorstellen, dass es i.d.R. performanter (und einfacher) ist, die Zeilen einfach komplett abschnittsweise in eine neue StringList zu kopieren.
Das Insert/Delete ist lediglich abhängig von der Anzahl der Zeilen im Block (hier 30). Mit deinem Vorschlag müssen immer alle Zeilen (80000) angefasst werden.

Hier noch eine alternative Lösung (beachtet auch eventuell hinterlegte Objects):
Delphi-Quellcode:
    lst.BeginUpdate;
    try
      for I := 0 to ACount - 1 do
        lst.Insert(ATargetLine, '');
      if ATargetLine < ASourceLine then
        ASourceLine := ASourceLine + ACount;
      for I := 0 to ACount - 1 do
        lst.Exchange(ASourceLine + I, ATargetLine + I);
      for I := 0 to ACount - 1 do
        lst.Delete(ASourceLine);
    finally
      lst.EndUpdate;
    end;
Exchange tauscht intern nur die String-Pointer aus, ist also recht effizient.

Da beim Insert/Delete immer nur Leerstrings (Nil-Pointer) betroffen sind, fällt da auch kein verdeckter Verwaltungsaufwand an.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
DieDolly

Registriert seit: 22. Jun 2018
2.175 Beiträge
 
#15

AW: StringList Textblöcke verschieben

  Alt 22. Mai 2019, 11:59
Zu diesem Beispiel habe ich die Frage, was denn ASourceLine ist?
Ist damit AStartLine gemeint? Wenn ja, verzeiht meine Unwissenheit

Obwohl, so ganz habe ich noch nicht verstanden wie da was verschoben wird. Meine Ergebnisse sind immer irgendwie komisch.

VerschiebeZeilen(sl, 0, 4, 8);
Zitat:
4

5
6
0
1
2
3
7
8
9

10
11
12
13
14


Geändert von DieDolly (22. Mai 2019 um 12:09 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Moombas
Moombas

Registriert seit: 22. Mär 2017
Ort: bei Flensburg
525 Beiträge
 
FreePascal / Lazarus
 
#16

AW: StringList Textblöcke verschieben

  Alt 22. Mai 2019, 12:23
Naja, 0 ist der Start, 4 das Ende (bei Zahlen 0-x ist Position 4 die "3" hier also 0-3) und schiebt es an Position 8 (bei Zahlen 0-x ist dies also 8-1 = da wo die 7 gestanden hat).

Das Ergebnis passt also.
Würdest du nun VerschiebeZeilen(sl, 1, 5, 11); schreiben, müsste folgendes das Ergebnis sein (Zahlen 0-14):
Vorher:
  1. 0
  2. 1
  3. 2
  4. 3
  5. 4
  6. 5
  7. 6
  8. 7
  9. 8
  10. 9
  11. 10
  12. 11
  13. 12
  14. 13
  15. 14
Nachher:
  1. 0
  2. 6
  3. 7
  4. 8
  5. 9
  6. 10
  7. 1
  8. 2
  9. 3
  10. 4
  11. 5
  12. 11
  13. 12
  14. 13
  15. 14
Der Weg ist das Ziel aber man sollte auf dem Weg niemals das Ziel aus den Augen verlieren.

Geändert von Moombas (22. Mai 2019 um 12:30 Uhr)
  Mit Zitat antworten Zitat
DieDolly

Registriert seit: 22. Jun 2018
2.175 Beiträge
 
#17

AW: StringList Textblöcke verschieben

  Alt 22. Mai 2019, 12:30
So funktioniert es bei mir. Alle Leerzeichen werden auch richtig gesetzt. Anders schaffe ich das nicht. Und selbst dann ist es n9icht zuverlässig.

Ich möchte ja keine Zeilen vertauschen sondern nur einen Block von oben irgendwo ganz nach unten verschieben.

Delphi-Quellcode:
var
 sl, slTemp: TStringList;
 i, LineStart, LineEnd, LineTarget: Integer;
begin
 sl := TStringList.Create;
 slTemp := TStringList.Create;
 try
  sl.Add('0 [');
  sl.Add('1');
  sl.Add('2');
  sl.Add('3');
  sl.Add('4');
  sl.Add(']');

  sl.Add('');

  sl.Add('5 [');
  sl.Add('6');
  sl.Add('7');
  sl.Add('8');
  sl.Add('9');
  sl.Add(']');

  sl.Add('');

  sl.Add('10 [');
  sl.Add('11');
  sl.Add('12');
  sl.Add('13');
  sl.Add('14');
  sl.Add(']');

  sl.Add('');

  sl.Add('15 {');
  sl.Add('16');
  sl.Add('17');
  sl.Add('18');
  sl.Add('19');
  sl.Add('}');

 // hier hin soll die 5-9

  sl.Add('');

  sl.Add('A');
  sl.Add('B');
  sl.Add('C');

  LineStart := sl.IndexOf('0 [');
  for i := LineStart to sl.Count - 1 do
   begin
    if sl.Strings[i] = ']then
     begin
      LineEnd := i + 2;
      Break;
     end;
   end;

  LineTarget := sl.IndexOf('15 [');
  for i := LineTarget to sl.Count - 1 do
   begin
    if sl.Strings[i] = ']then
     begin
      LineTarget := i + 2;
      Break;
     end;
   end;

  sl.SaveToFile('output1.txt');

  VerschiebeZeilen(sl, LineStart, LineEnd, LineTarget);

  sl.SaveToFile('output2.txt');
 finally
  slTemp.Free;
  sl.Free;
 end;
end;

Geändert von DieDolly (22. Mai 2019 um 12:36 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe
Online

Registriert seit: 20. Jan 2006
Ort: Lübbecke
10.980 Beiträge
 
Delphi 12 Athens
 
#18

AW: StringList Textblöcke verschieben

  Alt 22. Mai 2019, 12:34
Zu diesem Beispiel habe ich die Frage, was denn ASourceLine ist?
Ist damit AStartLine gemeint?
Ja, da habe ich eine Inkonsistenz in der Benennung beseitigt: ASourceLine passt doch irgendwie besser zu ATargetLine, oder?
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Delphi.Narium

Registriert seit: 27. Nov 2017
2.415 Beiträge
 
Delphi 7 Professional
 
#19

AW: StringList Textblöcke verschieben

  Alt 22. Mai 2019, 12:35
Im ersten Versuch von mir war ein grober Fehler, habe ihn oben behoben.

Hier mal eine Version in PascalScript, sollte recht einfach übertragbar sein:
Delphi-Quellcode:
program Scriptname;

procedure VerschiebeZeilen(sl : TStringList; AStartLine : Integer; ACount : Integer; ATargetLine : Integer);
var
  slTemp : TStringList;
  i : Integer;
begin
  slTemp := TStringList.Create;
   // Die zu verschiebenden Zeilen sammeln.
  for i := AStartLine to AStartLine + ACount - 1 do slTemp.Add(sl[i]);
  // Nun die zu verschiebenden Zeilen löschen
  // Es wird immer AStartLine gelöscht, da dadurch die nachfolgenden Zeilen "nach vorne rutschen".
  for i := 1 to ACount do sl.Delete(AStartLine);
  // Und anschließend an der gewünschten Position einfügen.
  // Dabei wird mit der letzten Zeile der gesammelten Zeilen begonnen,
  // da diese bei jedem Einfügen einer neuen Zeile nach "hinten" verschoben werden.
  // Im Ergebnis bleibt dadurch die ursprüngliche Reihenfolge erhalten.
  for i := slTemp.Count - 1 downto 0 do sl.Insert(ATargetLine - ACount,slTemp[i]);
  slTemp.Free;
end;

var
  sl : TStringList;
begin
  sl := TStringList.Create;
  sl.Add('1'); sl.Add('2'); sl.Add('3'); sl.Add('4'); sl.Add('5');
  sl.Add(' ');
  sl.Add('6'); sl.Add('7'); sl.Add('8'); sl.Add('9'); sl.Add('10');
  sl.Add(' ');
  sl.Add('11'); sl.Add('12'); sl.Add('13'); sl.Add('14'); sl.Add('15');
  VerschiebeZeilen(sl,0,5,10);
  ShowMessage(sl.Text);
  sl.Free;
end.
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe
Online

Registriert seit: 20. Jan 2006
Ort: Lübbecke
10.980 Beiträge
 
Delphi 12 Athens
 
#20

AW: StringList Textblöcke verschieben

  Alt 22. Mai 2019, 12:42
Ich möchte ja keine Zeilen vertauschen sondern nur einen Block von oben irgendwo ganz nach unten verschieben.
Du hast offenbar den Algorithmus noch nicht durchschaut. Deswegen erläutere ich das mal:

Zunächst füge ich an der Zielposition eine ausreichende Anzahl Leerzeilen ein:
Delphi-Quellcode:
      for I := 0 to ACount - 1 do
        lst.Insert(ATargetLine, '');
Dann korrigiere ich den Wert von ASourceLine, falls sich die entsprechenden Zeilen durch das Einfügen nach hinten verschoben haben:
Delphi-Quellcode:
      if ATargetLine < ASourceLine then
        ASourceLine := ASourceLine + ACount;
Nun tausche ich die zu verschiebenden Zeilen mit den gerade eingefügten Leerzeilen aus:
Delphi-Quellcode:
      for I := 0 to ACount - 1 do
        lst.Exchange(ASourceLine + I, ATargetLine + I);
Damit landen die zu verschiebenden Zeilen schon mal an der gewünschten Zielposition und an der ursprünglichen Position sind nun die Leerzeilen.

Im letzten Schritt werden diese Leerzeilen wieder gelöscht:
Delphi-Quellcode:
      for I := 0 to ACount - 1 do
        lst.Delete(ASourceLine);
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:37 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