Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Gibts eine schnelle TStringList mit Spalten? (https://www.delphipraxis.net/154488-gibts-eine-schnelle-tstringlist-mit-spalten.html)

moelski 13. Sep 2010 10:23

Delphi-Version: 2010

Gibts eine schnelle TStringList mit Spalten?
 
Moin !

Gibt es eigentlich in Delphi eine Klasse ähnlich dem TStringlist, aber mit Spalten?
Wenn ich das Recht sehe kann TStringList ja nur eine "Spalte" und man müsste Daten ggf. mit einem Delimiter eintragen um Spalten zu simulieren.

Aber gibts sowas evtl auch fertig?

Ich suche etwas wo ich Rohdaten ablegen kann. Derzeit habe ich 2 Spalten (kann aber mehr werden):
Datum | RohDaten

Wichtig wäre das es (wie beim TStringList) direkt Funktionen zum Laden / Speichern gibt. Und natürlich Zugriff über Indexe.

Kennt da jemand was?

mkinzler 13. Sep 2010 10:27

AW: Gibts eine schnelle TStringList mit Spalten?
 
Hier könnte ein CSV-DataSet helfen

moelski 13. Sep 2010 10:35

AW: Gibts eine schnelle TStringList mit Spalten?
 
Moin !

Zitat:

CSV-DataSet
Ist das eine Klasse die mit Delphi kommt, oder ist das von den Jedirittern ?

Wenn letzteres, dann müsste ich weitersuchen. Denn Jedi verwenden wir nicht.

mkinzler 13. Sep 2010 10:38

AW: Gibts eine schnelle TStringList mit Spalten?
 
Jedi beinhaltet eines, es gibt aber auch andere.

Btw: Was spricht gegen die Jedi-Kompos?

moelski 13. Sep 2010 10:41

AW: Gibts eine schnelle TStringList mit Spalten?
 
Moin !

Zitat:

Was spricht gegen die Jedi-Kompos?
Nichts. Ich versuche allerdings meist Libs und Komponenten zu vermeiden die wir nicht unbedingt brauchen.
Und bis dato hats auch ohne Jedi ganz gut geklappt.

Brainstalker 13. Sep 2010 10:43

AW: Gibts eine schnelle TStringList mit Spalten?
 
Ich hatte vor Ewigkeiten mal das gleiche gesucht. Hier ist noch der Link zum Beitrag. Ich hab das auch selbst noch ein bisschen erweitert, kann dir den Quelltext aber gearde nicht geben.
Wenn Interesse besteht lad ich ihn dir aber gerne nachher hoch wenn ich zu Hause bin.

StringList

[EDIT]

Es ist dann also eine ObjectList die StringLists enthält. Das schöne daran ist auch das Zeilen mit unterschiedlich vielen Spalten möglich sind.

moelski 13. Sep 2010 10:48

AW: Gibts eine schnelle TStringList mit Spalten?
 
Moin !

Zitat:

Wenn Interesse besteht lad ich ihn dir aber gerne nachher hoch wenn ich zu Hause bin.
Das wäre nett :)

Kann das Teil auch Speichern / Laden und zwar in eine Datei?
Stelle mir das gerade etwas kompliziert vor wenn ich x Stringlisten in eine Datei beamen will ...

Helmi 13. Sep 2010 10:48

AW: Gibts eine schnelle TStringList mit Spalten?
 
Hallo,

schau dir mal die Funktionen "Names" und "Values" der StringList an.

Die StringList bietet schon von sich aus eine "Teilung" des Items
Aufbau: Name=Value

mittels
Delphi-Quellcode:
StringList.Names[i]
kann man sich den linken Teil vom Gleichheitszeichen aus auslesen, mit
Delphi-Quellcode:
StringList.Values[i]
den rechten Teil.

DeddyH 13. Sep 2010 10:54

AW: Gibts eine schnelle TStringList mit Spalten?
 
Das sind dann aber nur 2 "Spalten", es werden jedoch ggf. mehr benötigt.

Helmi 13. Sep 2010 10:57

AW: Gibts eine schnelle TStringList mit Spalten?
 
Zitat:

Zitat von DeddyH (Beitrag 1049210)
Das sind dann aber nur 2 "Spalten", es werden jedoch ggf. mehr benötigt.

oh ja - sorry - überlesen

DeddyH 13. Sep 2010 10:58

AW: Gibts eine schnelle TStringList mit Spalten?
 
Kann ja mal passieren ;)

moelski 13. Sep 2010 10:58

AW: Gibts eine schnelle TStringList mit Spalten?
 
Moin !

Und ich denke damit habe ich auch ein großes Problem : NameValueSeparator ...

Denn ich muss den Trenner angeben. Und genau das will ich nicht.

Bsp: Meine Rohdaten sind $GP12,23,34;35,6<CR>
Wenn jetzt der NameValueSeparator auf ; stehen würde ... Dann wird das kaum gut gehen.

Brainstalker 13. Sep 2010 11:02

AW: Gibts eine schnelle TStringList mit Spalten?
 
Ich glaub ich hatte da nicht extra ne SaveToFile funktion drin, da ich die nur intern verwendet habe. Ansonsten sollte es aber auch nicht allzu schwer sein eine SaveToFile Funktion zu schreiben.
Wie es mit der Performance aussieht weiß ich allerdings nicht. Bietet die TObjectList eigentlich eine SaveToFile? Oder brauchst du die gespeicherte Datei als CSV?

moelski 13. Sep 2010 11:09

AW: Gibts eine schnelle TStringList mit Spalten?
 
Zitat:

Bietet die TObjectList eigentlich eine SaveToFile?
Nicht das ich wüsste.

Zitat:

Oder brauchst du die gespeicherte Datei als CSV?
Is mir voll schnuppe wie die Daten auf der Platte landen. Hauptsache ich kann sie wieder zurücklesen :)

alzaimar 13. Sep 2010 11:14

AW: Gibts eine schnelle TStringList mit Spalten?
 
Welches Interface sollte denn deine Tabellenkomponente haben?
Es ist bestimmt nicht schwer, die TStringlist-Klasse um die zusätzlichen Funktionen zu erweitern.
Ich kann mir das so vorstellen:
Delphi-Quellcode:
TMoelskiSeineStringList = Class (TStringlist)
public
  Property Header[Row : Integer] : String;
  Property RawData[Row, Col : Integer] String;
End;
Zusammen mit einer einfachen Explode-Funktion sollte eine generischen Implementierung nichts im Wege stehen: Ich schätze den Aufwand auf 10-20 Zeilen.

himitsu 13. Sep 2010 11:16

AW: Gibts eine schnelle TStringList mit Spalten?
 
Zitat:

Zitat von alzaimar (Beitrag 1049222)
Es ist bestimmt nicht schwer, die TStringlist-Klasse um die zusätzlichen Funktionen zu erweitern.

Jupp, z.B. auch über die Class-Helper, falls man keine neue Klasse möchte.

Und zum Aufteilen gibt es unzählige Explodefunktionen.
(wobei da auch schnell was kleines selbstgebastelt ist)

alzaimar 13. Sep 2010 13:23

AW: Gibts eine schnelle TStringList mit Spalten?
 
Zitat:

Zitat von himitsu (Beitrag 1049224)
Jupp, z.B. auch über die Class-Helper, falls man keine neue Klasse möchte.

...Das wollte ich nicht vorschlagen, weil wir ja nicht die TStringList-Klasse erweitern, sondern eine gänzlich neue Klasse erstellen wollen/sollten/könnten.

p80286 13. Sep 2010 13:25

AW: Gibts eine schnelle TStringList mit Spalten?
 
Wenn ich richtig gelesen habe, soll am besten auch noch ein Index mitgeliefert werden.
Auf welche "Spalte(n)" ?
So sehr ich dagen bin, sich für 1000 Adresssätze gleich eine Embedded-DB zuzulegen, hier wäre dies wohl angebracht.
Zitat:

Zitat von moelski (Beitrag 1049213)
Und ich denke damit habe ich auch ein großes Problem : NameValueSeparator ...

Denn ich muss den Trenner angeben. Und genau das will ich nicht.

Bsp: Meine Rohdaten sind $GP12,23,34;35,6<CR>
Wenn jetzt der NameValueSeparator auf ; stehen würde ... Dann wird das kaum gut gehen.

Ach Ja ? und warum nicht? wenn wir mal von Unicode absehen, eins von den 250 Zeichen sollte doch wohl als "Fíeldseperator" brauchbar sein.



Grüße
K-H

moelski 13. Sep 2010 14:06

AW: Gibts eine schnelle TStringList mit Spalten?
 
Zitat:

wenn wir mal von Unicode absehen, eins von den 250 Zeichen sollte doch wohl als "Fíeldseperator" brauchbar sein.
Nein. Was da an Rohdaten ankommt kann alles mögliche sein. Da bleibt eben kein Trenner über.

Zitat:

Wenn ich richtig gelesen habe, soll am besten auch noch ein Index mitgeliefert werden.
Auf welche "Spalte(n)" ?
ein Index auf die Reihen würde genügen.

Zitat:

Embedded-DB
Ist aber vermutlich nicht so performant wie eine Lösung mittels einfacher Liste ...

p80286 13. Sep 2010 15:00

AW: Gibts eine schnelle TStringList mit Spalten?
 
Zitat:

Zitat von moelski (Beitrag 1049278)
Zitat:

wenn wir mal von Unicode absehen, eins von den 250 Zeichen sollte doch wohl als "Fíeldseperator" brauchbar sein.
Nein. Was da an Rohdaten ankommt kann alles mögliche sein. Da bleibt eben kein Trenner über.

Dann sollten wir uns ganz schnell von Strings verabschieden,und zu einem Binären Format wechseln. (und sei es ein mißbrauchter Shortstring)

Zitat:

Zitat von moelski (Beitrag 1049278)
Zitat:

Wenn ich richtig gelesen habe, soll am besten auch noch ein Index mitgeliefert werden.
Auf welche "Spalte(n)" ?
ein Index auf die Reihen würde genügen.

Im allgemeinen wird der Index aus den Daten gebildet, nach denen gesucht wird. Z.B. Name, Erfassungsdatum etc.
Die "Reihennr / Satznummer" kann man zwar auch indizieren, aber bei einer Suche nach Inhalten wäre das nicht sehr zielführend.

Zitat:

Zitat von moelski (Beitrag 1049278)
Zitat:

Embedded-DB
Ist aber vermutlich nicht so performant wie eine Lösung mittels einfacher Liste ...

Um eine DB zu schlagen, muß Du eine DB-Ähnliche Struktur erstellen!
Alleine das Erstellen dieser Struktur, (wie auch immer sie konkret aussieht) fällt im täglichen Betrieb der DB fort. Da hast Du nur noch eine Chance mit handoptimierten Algorithmen und viiieel Assembler. Ob das den Aufwand lohnt?

Gruß
K-H

alzaimar 13. Sep 2010 15:29

AW: Gibts eine schnelle TStringList mit Spalten?
 
Zitat:

Zitat von p80286 (Beitrag 1049298)
Zitat:

Zitat von moelski (Beitrag 1049278)
Ist aber vermutlich nicht so performant wie eine Lösung mittels einfacher Liste ...

Um eine DB zu schlagen, muß Du eine DB-Ähnliche Struktur erstellen!...Da hast Du nur noch eine Chance mit handoptimierten Algorithmen und viiieel Assembler. Ob das den Aufwand lohnt?

Entschuldige, aber das ist Quatsch. So ziemlich jede interne (sortierte) Listenstruktur ist performanter als eine DB. Großartige Verrenkungen muss man noch nicht einmal anstellen: Eine sortierte Liste mit binary Search reicht vollkommen. Performancetechnisch total zerbröseln kann man jede DB mit einem Red-Black-Tree, einer Hashmap oder einer Kombination. Dafür muss man dann aber für jede Informationsabfrage einen neuen Algorithmus schreiben.

Brainstalker 13. Sep 2010 17:37

AW: Gibts eine schnelle TStringList mit Spalten?
 
Liste der Anhänge anzeigen (Anzahl: 1)
Also hier die versprochene Datei. Ist aber glaub ich nicht so besonders brauchbar für dich. Kein Save und Load, ich dachte ich hätte damals mehr implementiert.

Neumann 13. Sep 2010 18:49

AW: Gibts eine schnelle TStringList mit Spalten?
 
Hallo,

warum nicht ein ClientDataset benutzen? Kann Speichern, Lesen, man Sortierkriterien festlegen. Bei Daten in einer Tabelle ideal.

Gruß

Ralf

alzaimar 13. Sep 2010 19:08

AW: Gibts eine schnelle TStringList mit Spalten?
 
Die Daten liegen aber in einem proprietären Stringformat vor. Natürlich kann man sie dann in ein CDS o.ä (z.b Memory Dataset) überführen.

p80286 14. Sep 2010 09:24

AW: Gibts eine schnelle TStringList mit Spalten?
 
Zitat:

Zitat von alzaimar (Beitrag 1049309)
Zitat:

Zitat von p80286 (Beitrag 1049298)
Zitat:

Zitat von moelski (Beitrag 1049278)
Ist aber vermutlich nicht so performant wie eine Lösung mittels einfacher Liste ...

Um eine DB zu schlagen, muß Du eine DB-Ähnliche Struktur erstellen!...Da hast Du nur noch eine Chance mit handoptimierten Algorithmen und viiieel Assembler. Ob das den Aufwand lohnt?

Entschuldige, aber das ist Quatsch. So ziemlich jede interne (sortierte) Listenstruktur ist performanter als eine DB. Großartige Verrenkungen muss man noch nicht einmal anstellen: Eine sortierte Liste mit binary Search reicht vollkommen. Performancetechnisch total zerbröseln kann man jede DB mit einem Red-Black-Tree, einer Hashmap oder einer Kombination. Dafür muss man dann aber für jede Informationsabfrage einen neuen Algorithmus schreiben.

Okay geschenkt, ich war zu "Listenfixiert". Aber was bitte ist ein "Red-Black-Tree"? (der Wikipediaartikel ist mir zu farblastig). Mir sind nur die "Nil"-Blätter aufgefallen.

Gruß
K-H

Satty67 14. Sep 2010 09:33

AW: Gibts eine schnelle TStringList mit Spalten?
 
In C# bin ich dabei mit ein ObjectTable als Basis für ein nachgebautes StringGrid zu entwerfen. Das ist genauso leicht in Delphi realisierbar.

Es ist im Prinzip eine einfach Klasse mit dem Member
Delphi-Quellcode:
FObjectColumns = array of TObjectList;
.
auf Strings spezialisiert könnte man
Delphi-Quellcode:
FStringColumns = array of TStringList
nehmen.

Dabei ist jede Spalte eine TStringlist, lässt sich sehr einfach verwalten und um weitere Spalten erweitern. Zugriff erfolgt wie bei StringGrid via
Delphi-Quellcode:
function Cell(row, column : Integer): String;
begin
  sl := FStringColumns[column];
  result := sl[row];
end;
Also zumindest eine Basis-Funktionalität mit Get/SetCell und dynamischer Anpassung der Reihen/Spalten ist recht fix gemacht

PS: Wenn es interessant ist, kann ich heute Abend schnell eine Basisklasse schreiben, die Logik kann ich ja aus dem fertigen Code in C# übernehmen und muss nicht mehr viel dabei denken...

mleyen 14. Sep 2010 09:41

AW: Gibts eine schnelle TStringList mit Spalten?
 
Zitat:

Zitat von Satty67 (Beitrag 1049477)
Also zumindest eine Basis-Funktionalität mit Get/SetCell und dynamischer Anpassung der Reihen/Spalten ist recht fix gemacht

PS: Wenn es interessant ist, kann ich heute Abend schnell eine Basisklasse schreiben, die Logik kann ich ja aus dem fertigen Code in C# übernehmen und muss nicht mehr viel dabei denken...

Das Problem ist aber SaveToFile / LoadFromFile ohne Delim zu implementieren.
Der Rest ist echt einfach:
Delphi-Quellcode:
property Strings[const Row, Col: Integer]: string read getStrings write setStrings;
+ GetCol(ColId): StringList + Add/DelCol(ColId)

Satty67 14. Sep 2010 10:09

AW: Gibts eine schnelle TStringList mit Spalten?
 
SaveToFile denke ich ist einfach, eine CSV Struktur genauso wie eine PlainText-Struktur. (Müssen ja nur die Spalten einer Reihe entsprechend kombiniert werden)

Eher das LoadFromFile, wenn keine Delimiter oder CSV Struktur vorhanden ist. Aber das Problem einer Einleselogik hat er ja dann immer und muss gelöst werden, sonst braucht man gar kein Container mit Spalten dafür zu suchen.

Edit: So, habe mal etwas gebastelt (bzw. eine angefangene C# Klasse umgeschrieben)

Das wechsen zw. den Sprachen überfordert mich, hatte jetzt dann keinen Nerv mehr (=/:=/==/" "/' ') macht mich verrückt :wink:

Cell ist zero-based wie beim StringGrid. Row/ColCount muss man nicht setzen, passt sich dynamisch an. Nur zu Abfrage oder wenn man die Tabelle zum Speicher sparen reduzieren will aufzurufen. Ist nur eine Basis, also Fehlerbehandlung und Endfunktionalität soll reinmachen, wer es benutzen möchte!
Delphi-Quellcode:
unit UStringTable;

interface

uses
  Classes;

type
  TStringTable = class
  private
    FTableColumns : array of TStringList;
    FDelimiter    : String;
    FBoundary     : String;
    FCrNlScheme   : String;

    function GetCell(Row, Col: Integer): String;
    function GetColCount: Integer;
    function GetRowCount: Integer;
    procedure SetCell(Row, Col: Integer; const Value: String);
    procedure SetColCount(const Value: Integer);
    procedure SetRowCount(const Value: Integer);
    function GetCSV: String;
    procedure SetCSV(const Value: String);

  public
    constructor Create;
    destructor Destroy; override;

    procedure Clear;
    function CSVtoFile(Filepath : String): Integer;

    property Delimiter : String Read FDelimiter Write FDelimiter;
    property Boundary : String Read FBoundary Write FBoundary;
    property CrNlScheme : String Read FCrNlScheme Write FCrNlScheme;

    property Cell[Row, Col: Integer]: String Read GetCell Write SetCell;
    property RowCount : Integer Read GetRowCount Write SetRowCount;
    property ColCount : Integer Read GetColCount Write SetColCount;
    property CSV : String Read GetCSV Write SetCSV;
  end;

implementation

{ TStringTable }

constructor TStringTable.Create;
begin
  FDelimiter := ',';
  FBoundary  := '"';
  FCrNlScheme := #13#10;
end;

destructor TStringTable.Destroy;
begin
  self.Clear;
  inherited;
end;

procedure TStringTable.Clear;
var
  i : Integer;
begin
  for i := 0 to Length(FTableColumns) -1 do
    FTableColumns[i].Free;
  SetLength(FTableColumns, 0);
end;

function TStringTable.GetColCount: Integer;
begin
  Result := length(FTableColumns);
end;

procedure TStringTable.SetColCount(const Value: Integer);
var
  i, j : Integer;
begin
  if Value < 0 then Exit;

  while (self.ColCount > Value) do
  begin
    i := Length(FTableColumns) - 1;
    FTableColumns[i].Free;
    SetLength(FTableColumns, i);
  end;

  while (self.ColCount < Value) do
  begin
    i := Length(FTableColumns);
    SetLength(FTableColumns, i + 1);
    FTableColumns[i] := TStringList.Create;
    // set new Column to current RowCount
    for j := 0 to self.RowCount -1 do
      FTableColumns[i].Add('');
  end;
end;

function TStringTable.GetRowCount: Integer;
begin
  if (Length(FTableColumns) > 0) then
    Result := FTableColumns[0].Count
  else
    Result := 0;
end;

procedure TStringTable.SetRowCount(const Value: Integer);
var
  i : Integer;
begin
  if Value < 0 then Exit;

  while (self.RowCount > Value) do
  begin
    for i := 0 to self.ColCount -1 do
      FTableColumns[i].Delete(self.ColCount -1);
  end;

  while (self.RowCount < Value) do
  begin
    for i := 0 to self.ColCount -1 do
      FTableColumns[i].Add('');
  end;
end;

function TStringTable.GetCell(Row, Col: Integer): String;
begin
  Result := FTableColumns[Col][Row];
end;

procedure TStringTable.SetCell(Row, Col: Integer; const Value: String);
begin
  if (Col >= self.ColCount) then
    self.ColCount := Col + 1;
  if (Row >= self.RowCount) then
    self.RowCount := Row + 1;

  FTableColumns[Col][Row] := Value;
end;

function TStringTable.GetCSV: String;
var
  r, c, rCount, cCount : Integer;
begin
  Result := '';
  rCount := self.RowCount;
  cCount := self.ColCount;

  for r := 0 to rCount -1 do
  begin
    for c := 0 to cCount -1 do
    begin
      Result := Result +
                FBoundary +
                self.Cell[r, c] +
                FBoundary;
      if (c < (cCount - 1)) then
        Result := Result + FDelimiter;
    end;
    if (r < (rCount -1)) then
      Result := Result + FCrNlScheme;
  end;
end;

procedure TStringTable.SetCSV(const Value: String);
begin
  // ToDo...
end;

function TStringTable.CSVtoFile(Filepath: String): Integer;
begin
  // ToDo...
  Result := 0; // returns last Win32 Error
end;

end.
.
Füllen mit 10.000.000 String-Felder â 10 Zeichen Länge dauert 3 Sekunden, denke das ist ganz brauchbar. GetCSV reichte mir erstmal, um das Ergebnis bzw. den Inhalt der Tabelle zu testen


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:44 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