![]() |
String in Array einlesen
Hallo,
ich hab hier ne kleine rechnung, in der ich ungefähr 100 Werte in jeweils 3 Spalten erzeugt habe und die dann als .txt ausgebe. So z.B.
Delphi-Quellcode:
mystring := Spalte1 + #9 + Spalte2 + #9 + Spalte3 + #13#10;
Ich möchte nun die Werte in Spalte 2 der Größe nach ordnen, mit den zugehörigen Werten aus Spalte 1 und 3. Ich dachte nun, dass ich die Werte in ein Array einlese und danach den Quicksort oder BubbleSort Algorithmus darauf anwende. Bei mir fehlt es leider an Programmiererfahrung, wie ich das mache. Kann mir da bitte jemand helfen wie ich das am besten mache. Vielen Dank |
AW: String in Array einlesen
mein Tipp speichere es in eine Datenbank ob echt oder Memory (TClientDataset) und lasse es dort sortieren ....
das ist viel weniger Code und schnell ist es auch noch |
AW: String in Array einlesen
Die alles entscheidende Frage: Für welche Delphi Version?
Mit den Generics ist das sehr simpel gemacht:
Delphi-Quellcode:
und ohne Generics geht das so
uses
System.SysUtils, System.Generics.Defaults, System.Generics.Collections; type TMyData = record Col1, Col2, Col3 : string; end; var AList : TList<TMyData>; AList.Sort( TComparer<TMyData>.Construct( function ( const Left, Right : TMyData ) : Integer begin Result := CompareStr( Left.Col2, Right.Col2 ); end ) );
Delphi-Quellcode:
type
PMyData = ^TMyData; TMyData = record Col1, Col2, Col3 : string; end; function CompareMyDataCol2( Item1, Item2 : Pointer ) : Integer; begin Result := CompareStr( PMyData( Item1 ).Col2, PMyData( Item2 ).Col2 ); end; var AList : TList; AList.Sort( @CompareMyDataCol2 ); |
AW: String in Array einlesen
hallo jetzt muss ich als alter Delphi Profi (D5) echt mal dumm fragen, was machst Du da ?
Du vergleichst Strings, ok das gibt die Sortierreihenfolge, ruft die Sortfunktion deine procedure solange auf bis keine Veränderung mehr auftritt oder wie muss man das verstehen ? |
AW: String in Array einlesen
@jupiter4065139
ich denke am einfachsten und schnellsten geht es, wenn du die Strings in eine TListBox einliest und die Property "Sorted" auf true setzt, und anschließend die TListBox.Items in eine Textdatei schreibst. |
AW: String in Array einlesen
Zitat:
![]() [edit] @musicman: das würde funktionieren, wenn es sich nur um einen String handeln würde, hier ist es aber ein Verbund aus mehreren Strings. Die muss man nun irgendwie zusammenhaltenm sei es in einem Record oder einer Klasse, und dann den Verbund vergleichen. [/edit] |
AW: String in Array einlesen
Zitat:
Zitat:
Delphi-Quellcode:
gehen ... aber einen Comparer an die Liste zu klatschen ist doch so was von fix gemacht, warum dieser Umstand?
TStringList
|
AW: String in Array einlesen
Hallo Deddy,
das ist mir schon klar. Je nach dem wie du den String zusammensetzt wird auch sortiert. Für die Ausgabe kann man den string ja wieder anders zusammensetzen. Also beispielsweise SP2 + SP1 + SP3 als string sortieren und beim Ausgeben wieder SP1 + SP2 + SP3. So hab ich's jedenfalls gemeint. Sorry, wenn das falsch rüber gekommen ist. Abgesehen davon, die Sortierfunktion von TList muss diese "Umsortierung" ja ebenfalls durchführen. Wenn der "Input" SP1+SP2+SP3 ist, aber nach SP2 sortiert werden soll, dann funktioniert ein einfacher string-sort nicht. Der string muss zuerst nach SP2+SP1+SP3 umgebaut werden. Oder ich habe den Sinn der Frage nicht ganz verstanden, was ich ja nicht ausschließen möchte. Abgesehen davon, der Vorteil der Listbox ist meiner Ansicht nach, dass man das Ergebnis schon am BS betrachten kann. |
AW: String in Array einlesen
Klingt irgendwie danach mit einem Airbus A380 über die Autobahn an Paris und Rom vorbeizufahren, nur um den Nachbarn zu besuchen.
|
AW: String in Array einlesen
Lange Rede, ...
Delphi-Quellcode:
uses
Classes, SysUtils; function GetTextCol(const AValue: string; AIndex: Integer): string; var iPos: Integer; begin Result := AValue; {Spalten 0 .. AIndex-1 löschen} while AIndex > 0 do begin iPos := Pos(Char(#9), Result); if iPos = 0 then begin Result := ''; Exit; end; Delete(Result, 1, iPos); Dec(AIndex); end; {Spalten AIndex+1 löschen} iPos := Pos(Char(#9), Result); if iPos > 0 then Delete(Result, iPos, Length(Result)); end; function MyCompareFn(List: TStringList; Index1, Index2: Integer): Integer; var s1, s2: string; begin s1 := GetTextCol(List[Index1], 1); s2 := GetTextCol(List[Index2], 1); if List.CaseSensitive then Result := AnsiCompareStr(s1, s2) else Result := AnsiCompareText(s1, s2); end; var SL: TStringList; begin SL := TStringList.Create; try SL.LoadFromFile('Text.txt'); SL.CustomSort(MyCompareFn); SL.SaveToFile('MyText.txt'); finally SL.Free; end; end; |
AW: String in Array einlesen
:?:
also Obiwan (Sir Rufo), ich will mich nicht so weit aus dem Fenster lehnen ich würde mal behaupten das dein Quellcode nicht geht, bzw nicht das macht was er will: in SQL ausgedrückt will er Select Sp1,sp2,sp3 from wasauchimmer order by sp2 |
AW: String in Array einlesen
@Sir Rufo Stimmt, abgesehen davon, dass
Delphi-Quellcode:
in diesem Fall eben so einfach nicht funktioniert
Result := CompareStr( Left.Col2, Right.Col2 );
|
AW: String in Array einlesen
Ich will mal versuchen das auf die altmodische Art zu Lösen:
Code:
var ozeile:integer; // in die Form zwei Tmemo und eine Tlistbox einfügen .... memo1.lines.loadfromfile('ursprung.txt'); // Textladen Listbox1.items.clear; // Zwischenpuffer zum sortieren Listbox1.Sorted:=False; // Sortierung aus for i:=0 to memo1.lines.count-1 do begin if Pos(#9,Memo1.lines[i])>0 then begin // SP2 ermitteln ListBox1.items.Add(Copy(Memo1.lines[i],Pos(#9,Memo1.lines[i])+1),255); // Sp2+sp3 einsetzen ListBox1.Items[ListBox1.items.count-1]:=Copy(ListBox1.Items[ListBox1.items.count-1],1,Pos(#9,ListBox1.Items[ListBox1.items.count-1])))+intTostr(i); // sp3 entfernen und ID mit übergeben end; Listbox1.Sorted:=True; // sortieren memo2.Lines.clear; // hier nun das ergebnis speichern for i:=0 to ListBox1.items.count-1 do begin // ursprüngliche zeile herausfinden ozeile:=StrToInt(Copy(ListBox1.items[i],Pos(#9,ListBox1.Items[i]+1),255)); //id der sortierten Listbox auslesen memo2.lines.Add(memo1.lines[ozeile]); // ursprüngliche zeile übergeben end; // // in memo2 steht nun das ergebnis Sollte ich Tippfehler oder Klammern vergessen haben, so bitte ich dies zu entschuldigen, da ich das hier einfach mal so reingehackt habe ..... |
AW: String in Array einlesen
Wie kommt Ihr eigentlich darauf, dass das nicht funktionieren soll? In diesem Beispiel ist FList ein privates Formularfeld vom Typ TList.
Delphi-Quellcode:
Das ergibt dann folgende Ausgabe:
type
PRec = ^TRec; TRec = record Col1, Col2, Col3: string; end; ... //Befüllen var NewRec: PRec; begin New(NewRec); NewRec^.Col1 := 'Anton'; NewRec^.Col2 := 'Berta'; NewRec^.Col3 := 'Cäsar'; FList.Add(NewRec); New(NewRec); NewRec^.Col1 := 'August'; NewRec^.Col2 := 'Bär'; NewRec^.Col3 := 'C++'; FList.Add(NewRec); New(NewRec); NewRec^.Col1 := 'Auf der Mauer'; NewRec^.Col2 := 'Auf der Lauer'; NewRec^.Col3 := 'Dideldum dideldei'; FList.Add(NewRec); end; //Sortieren function CompareFunc(Item1, Item2: PRec): integer; begin Result := AnsiCompareStr(Item1^.Col2, Item2^.Col2); end; procedure TfrmTest.btnSortClick(Sender: TObject); begin FList.Sort(@CompareFunc); end; ... //Ausgeben for i := 0 to FList.Count - 1 do begin Rec := PRec(FList[i])^; mmoAusgabe.Lines.Add(Format('%s;%s;%s', [Rec.Col1, Rec.Col2, Rec.Col3])); end; Zitat:
|
AW: String in Array einlesen
@DeddyH
genau so :) |
AW: String in Array einlesen
Zitat:
Zitat:
|
AW: String in Array einlesen
Evtl. handelt es sich hier um das Hummel-Paradoxon.
Mein Code weiß nicht, dass er gar nicht funktionieren darf, und macht es trotzdem ;) Ein kleines Testprogramm mit und ohne Generics
Delphi-Quellcode:
program ListSort;
{$APPTYPE CONSOLE} {$R *.res} // Generics-Switch {$IF CompilerVersion>=20} {$DEFINE GENERICS} {$IFEND} // uses {$IFDEF GENERICS} System.Generics.Defaults, System.Generics.Collections, {$ENDIF} Classes, SysUtils; type PMyData = ^TMyData; TMyData = record Col1, Col2, Col3 : string; end; {$IFDEF GENERICS} procedure WriteList( AList : TList<TMyData> ); var LIdx : Integer; begin for LIdx := 0 to AList.Count - 1 do Writeln( AList[LIdx].Col1, ',', AList[LIdx].Col2, ',', AList[LIdx].Col3 ); end; procedure Test; var LList : TList<TMyData>; LRec : TMyData; begin Writeln( 'Generic Version' ); Writeln; LList := TList<TMyData>.Create; try // Add Data LRec.Col1 := 'a'; LRec.Col3 := 'c'; LRec.Col2 := 'z'; LList.Add( LRec ); LRec.Col2 := 'a'; LList.Add( LRec ); LRec.Col2 := 'm'; LList.Add( LRec ); // Output Data Writeln( 'Before Sort' ); WriteList( LList ); Writeln; // Sort Data LList.Sort( TComparer<TMyData>.Construct( function( const Left, Right : TMyData ) : Integer begin Result := CompareStr( Left.Col2, Right.Col2 ); end ) ); // Output Data Writeln( 'After Sort' ); WriteList( LList ); Writeln; finally LList.Free; end; end; {$ELSE} function CompareMyDataCol2( Item1, Item2 : Pointer ) : Integer; begin Result := CompareStr( PMyData( Item1 ).Col2, PMyData( Item2 ).Col2 ); end; procedure WriteList( AList : TList ); var LIdx : Integer; begin for LIdx := 0 to AList.Count - 1 do Writeln( PMyData( AList[LIdx] ).Col1, ',', PMyData( AList[LIdx] ).Col2, ',', PMyData( AList[LIdx] ).Col3 ); end; procedure AddData( AList : TList; ARec : TMyData ); var LNewRec : PMyData; begin New( LNewRec ); LNewRec^ := ARec; AList.Add( LNewRec ); end; procedure Test; var LList : TList; LRec : TMyData; begin Writeln( 'NON-Generic Version' ); Writeln; LList := TList.Create; try // Add Data LRec.Col1 := 'a'; LRec.Col3 := 'c'; LRec.Col2 := 'z'; AddData( LList, LRec ); LRec.Col2 := 'a'; AddData( LList, LRec ); LRec.Col2 := 'm'; AddData( LList, LRec ); // Output Data Writeln( 'Before Sort' ); WriteList( LList ); Writeln; // Sort Data LList.Sort( @CompareMyDataCol2 ); // Output Data Writeln( 'After Sort' ); WriteList( LList ); Writeln; finally LList.Free; end; end; {$ENDIF} begin try Test; except on E : Exception do Writeln( E.ClassName, ': ', E.Message ); end; ReadLn; end. |
AW: String in Array einlesen
OT:
@Sir Rufo : Lass dich nicht ärgern, ich finde deine Lösungen immer sehr kompetent, kurz und knackig. Da ich Informatik nicht studiert habe, muss sich da zwar mein Köpfchen oft sehr anstrengen um alles zu kapieren, aber wenn ichs dann kapiert habe, bin ich wieder ein Quäntchen schlauer und zufriedener als zuvor ... Ich mag Luke-Power 8-) |
AW: String in Array einlesen
Hab ich da etwas nicht mitbekommen?
Die Lösung von BLUP (hab ich jetzt nicht getestet oder ganz genau gelesen) ist doch wohl das, was gesucht wurde? Sir Rufo hat es mit Feldern/Records gelöst, was meiner Meinung nach sauberer ist. Ist übrigens ein schönes Beispiel dafür, daß man die Darstellung von den Daten trennen sollte. (Peine Paris Salzgitter reicht auch, es muß nicht immer Airbus sein ) Gruß K-H |
AW: String in Array einlesen
Zitat:
(Danke für die Blumen :)) |
AW: String in Array einlesen
Hallo,
also bitte mal der Reihe nach. Vielleicht hab ich ja was falsch verstanden. Dann korrigiert mich bitte. So schrieb es der TE: Zitat:
Spalte 2 + Spalte 1 + Spalte 3, also nicht nur nach Spalte 2. Demzufolge kann die Lösung mit TList so nicht funktionieren, weil eben NUR nach Spalte 2 sortiert wird, und Spalte 1 und 3 werden in der Sortierung ignoriert. Der record könnte dann beispielsweise so aussehen:
Delphi-Quellcode:
...wobei Cols dann Col2+Col1+Col3 wäre und die Sortierung dann...
type
PMyData = ^TMyData; TMyData = record Col1, Col2, Col3 : string; Cols : string; end;
Delphi-Quellcode:
....und bei der Ausgabe dann wieder den string zusammensetzen aus Col1+Col2+Col3.
function CompareMyDataCol2( Item1, Item2 : Pointer ) : Integer;
begin Result := CompareStr( PMyData( Item1 ).Cols, PMyData( Item2 ).Cols ); end; |
AW: String in Array einlesen
Das hatten wir doch schon
In SQL würde das so aussehen
SQL-Code:
Wie er Strings sortiert weiß er, aber nicht wie er nach der Sortierung den logischen Zusammenhang wieder hinbekommt. ;)
SELECT
Col1, Col2, Col3 FROM MyTable ORDER BY Col2 |
AW: String in Array einlesen
Das habe ich (und zumindest Sir Rufo auch) so nicht verstanden. Vielmehr geht es darum, nach Spalte 2 zu sortieren, aber die Zugehörigkeit zu den anderen beiden Werten nicht zu verlieren. Und selbst wenn nach mehreren Spalten in einer bestimmten Reihenfolge sortiert werden soll, erweitert man den Callback entsprechend und fertig.
Delphi-Quellcode:
function CompareFunc(Item1, Item2: PRec): integer;
begin Result := AnsiCompareStr(Item1^.Col2, Item2^.Col2); if Result = 0 then Result := AnsiCompareStr(Item1^.Col1, Item2^.Col1); if Result = 0 then Result := AnsiCompareStr(Item1^.Col3, Item2^.Col3); end; |
AW: String in Array einlesen
Das ist der Punkt bzw. Unterschied...ich hab's so verstanden:
Code:
SELECT
Col1, Col2, Col3 FROM MyTable ORDER BY Col2, Col1, Col3 |
AW: String in Array einlesen
Hallo an alle:
mal zum Verständnis: man will niemanden ärgern, wir wollen ja alle nur mal Helfen und manchmal lernt man was neues :thumb: was DeddyH in seinem Quellcode macht und Sir Rufo im Quellcode (seinen ersten Beitrag angedeutet hat), ist einen Record der Liste zu übergeben und die Sortierfunktion entsprechen umzuleiten, das nach dem 2'ten Feld sortiert wird. Meine Lösung macht das auf altbackene weise, so kann man es aber nachvollziehen (ist aber langsamer). |
AW: String in Array einlesen
Nunja, das Hauptproblem, das ich persönlich mit Deinem Code habe, ist die Vermischung von Logik und Darstellung. Es liest sich so, als ob man unbedingt Memos bzw. Listboxen bräuchte, um das Problem zu lösen. Das geht natürlich auch, ist aber IMO unschön.
Nothing for ungood |
AW: String in Array einlesen
Nun ich wurde mal als Listboxenprogrammierer beschimpft :thumb: um schnell eine Lösung zu machen, die würde ja einem Prof nicht gefallen, aber der wird ja auch nicht nach dem Ergebnis bezahlt sondern nur nach .... :roll:
Mit XE4 und iOS wurde mir klar, das ist das neueste vom neuen, da geht ja fast alles über meine liebe Listbox und die kann ja jetzt auch richtig viel :lol: |
AW: String in Array einlesen
Zitat:
|
AW: String in Array einlesen
Hallo,
vielen Dank für die rege Beteiligung. Ich war letzter zeit verhindert und kann das Problem jetzt erst wieder anpacken. Ich bin zur Zeit dabei mein String in records einzulesen wie bei DeddyH
Delphi-Quellcode:
wie gesagt mein string sieht folgendermaßen aus
type
PRec = ^TRec; TRec = record Col1, Col2, Col3: string; end; ... //Befüllen var NewRec: PRec; begin New(NewRec); NewRec^.Col1 := 'Anton'; NewRec^.Col2 := 'Berta'; NewRec^.Col3 := 'Cäsar'; FList.Add(NewRec); New(NewRec); NewRec^.Col1 := 'August'; NewRec^.Col2 := 'Bär'; NewRec^.Col3 := 'C++'; FList.Add(NewRec); New(NewRec); NewRec^.Col1 := 'Auf der Mauer'; NewRec^.Col2 := 'Auf der Lauer'; NewRec^.Col3 := 'Dideldum dideldei'; FList.Add(NewRec); end
Delphi-Quellcode:
mystring := col1 + #9 + col2 + #9 +col3;
mit ungefähr hundert zeilen. Wie mach ich denn das am Besten den Pointer NewRec^.Col1 eine Schleife zu verpassen das der mir nur die col1 mit den 100 Werten aus dem string einliest. |
AW: String in Array einlesen
Ein wenig konfus was Du da willst.
Gehen wir mal davon aus, daß Du eine Funktion hast, die die Inhalte aus einem String auslesen kann (
Delphi-Quellcode:
)
wert:=getcol(i,mystring);
dann müßte die Verarbeitung ungefähr so aussehen:
Delphi-Quellcode:
Wenn Du nur eine Spalte lesen willst dann vllt. so:
var
NewRec: PRec; begin Stringlist:=tStringlist.Create; Stringlist.Loadfromfile('meinedaten.txt'); for i:=0 to Stringlist.count-1 do begin New(NewRec); NewRec^.Col1 := getcol(1,Stringlist[i]); NewRec^.Col2 := getcol(2,Stringlist[i]); NewRec^.Col3 := getcol(3,Stringlist[i]); FList.Add(NewRec); end;
Delphi-Quellcode:
var
NewRec: PRec; begin Stringlist:=tStringlist.Create; Stringlist.Loadfromfile('meinedaten.txt'); for i:=0 to Stringlist.count-1 do begin New(NewRec); NewRec^.Col1 := getcol(1,Stringlist[i]); NewRec^.Col2 := ''; NewRec^.Col3 := ''; FList.Add(NewRec); end; U.U wäre es besser mit einem
Delphi-Quellcode:
zu arbeiten, da könntest Du die einzelnen spalten direkt über einen Index ansprechen.
Array of Col
Aber bitte nicht vergessen vorher alle Felder zu initialsieren. Gruß K-H |
AW: String in Array einlesen
ok, wie müsste die getcol Funktion ungefähr aussehen?
ich hab noch ne frage: Wie müsste ich denn das machen um den gesamten string mit allen zeilen in die Liste einzulesen
Delphi-Quellcode:
so gibt er mir nur eine zeile wieder
mystring := col1 + #9 + col2 + #9 + col3 + #13#10; //AK
strl:=Tstringlist.Create; strl.add(mystring); strl.SaveToFile('liste.txt'); |
AW: String in Array einlesen
Dann kommen wir doch mal hierauf zurück
Zitat:
Wenn es denn unbedingt der Text sein muß dann vllt so
Delphi-Quellcode:
Ist nur so runter getippt. Beachte das lfnr von 0..irgendwas geht!
function Getcol(lfnr:integer;mytext:string;delim:char);
var delimll:tstringlist; begin delimll:=Tstringlist.create; delimll.delimter:=delim; delimll.Delimitedtext:=mytext; result:=delimll[lfnr]; delimll.free; end; Gruß K-H end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:02 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz