CommaText, nur Komma

Rund um die LCL und andere Komponenten
Antworten
Mathias
Beiträge: 7219
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

CommaText, nur Komma

Beitrag von Mathias »

Wieso nimmt CommaText nicht nur das Komma als Trenner ?

Code: Alles auswählen

ListBox1.Items.CommaText := '1,2,1 1,2 2';    
Der obige Code macht

Code: Alles auswählen

1
2
1
1
2
2
erwünschte wäre

Code: Alles auswählen

1
2
1 1
2 2
.
Geht die nur über den Umweg mit DelimitedText ?
Oder mit diesem Umweg:

Code: Alles auswählen

  ListBox1.Items.AddStrings('1,2,1 1,2 2'.Split([',']));
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Warf
Beiträge: 2270
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: CommaText, nur Komma

Beitrag von Warf »

CommaText benutzt intern DelimitedText, ist also praktisch eine kurzform für Delimiter auf komma setzen und danach DelimitedText setzen, und damit abhängig von StrictDelimiter ob nur der Delimiter benutzt wird (in diesem fall Komma) oder auch spaces, tabs oder anderes.
Eine andere option ists quotes zu benutzen, also z.B. als Eingabe

Code: Alles auswählen

1, "1 1", 2, "2 2"
Das hat den vorteil das ohne strict delimiter du leer zeichen nach den kommas haben kannst. Wenn deine daten natürlich keine Quotes haben, ists natürlich keine option (Strict delimiter hat noch ein paar andere vorteile, so kannst du z.B. ne ganze CSV datei mit nur einem aufruf parsen und dann einfach modulo spaltenanzahl auf die Reihen zugreifen, du musst aber natürlich dafür eine dazu kompatible datei haben damit das sinn ergibt)

wp_xyz
Beiträge: 5377
Registriert: Fr 8. Apr 2011, 09:01

Re: CommaText, nur Komma

Beitrag von wp_xyz »

Vielleicht hat's Warf schon so gemeint, aber es funktioniert auch, wenn man StrictDelimiter auf true setzt:

Code: Alles auswählen

program Project1;
 
uses
  Classes;
 
var
  L: TStringList;
  s: String;
begin
  L := TStringList.Create;
  try
    L.StrictDelimiter := true;
    L.CommaText := '1,2,1 1,2 2';
 
    for s in L do
      WriteLn(s);
   finally
     L.Free;
   end;
end.
 

Mathias
Beiträge: 7219
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: CommaText, nur Komma

Beitrag von Mathias »

CommaText benutzt intern DelimitedText, ist also praktisch eine kurzform für Delimiter auf komma setzen und danach DelimitedText setzen, und damit abhängig von StrictDelimiter ob nur der Delimiter benutzt wird (in diesem fall Komma) oder auch spaces, tabs oder anderes.
So etwas verwirrt einem. Beim Bezeichner CommaText nimmt man an, das nur Kommas als Trenner gelten.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

wp_xyz
Beiträge: 5377
Registriert: Fr 8. Apr 2011, 09:01

Re: CommaText, nur Komma

Beitrag von wp_xyz »

Mathias hat geschrieben:
CommaText benutzt intern DelimitedText, ist also praktisch eine kurzform für Delimiter auf komma setzen und danach DelimitedText setzen, und damit abhängig von StrictDelimiter ob nur der Delimiter benutzt wird (in diesem fall Komma) oder auch spaces, tabs oder anderes.
So etwas verwirrt einem. Beim Bezeichner CommaText nimmt man an, das nur Kommas als Trenner gelten.
Eigentlich hätte man sich den CommaText sparen können, DelimitedText hätte gereicht. Aber wahrscheinlich hatte Delphi zuerst den CommaText eingeführt; man bemerkte dann, dass man auch Strichpunkt oder Tab als Begrenzer brauchen kann, und hat den DelimitedText eingeführt - und ab da konnte man nicht mehr zurück. Und FPC musste aus Kompatibilitätsgründen nachziehen.

Mathias
Beiträge: 7219
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: CommaText, nur Komma

Beitrag von Mathias »

Dies ist auch noch eine Variante, um eine StringList ab zufüllen:

Code: Alles auswählen

const
  sa:TStringArray=('abc','def','ghi');
 
procedure TForm1.FormCreate(Sender: TObject);
begin
  ListBox1.Items.AddStrings(sa);
end;   
String.Splitt(...); ist das flexibelste, das ich kenne.

Code: Alles auswählen

var
  s: string = 'abc,def;ghi';
  sa: TStringArray;
 
procedure TForm1.FormCreate(Sender: TObject);
begin
  sa := s.Split([',', ';']);
  ListBox1.Items.AddStrings(sa);
end;
Beim Delimeter kann man nur ein Trennzeichen eingeben.
Dazu noch eine Frage, wieso hat CommaText mit mehreren Zeichen getrennt ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

wp_xyz
Beiträge: 5377
Registriert: Fr 8. Apr 2011, 09:01

Re: CommaText, nur Komma

Beitrag von wp_xyz »

Mathias hat geschrieben:Beim Delimeter kann man nur ein Trennzeichen eingeben.
Dazu noch eine Frage, wieso hat CommaText mit mehreren Zeichen getrennt ?
Weil DelimitedText (und damit auch CommaText als Spezialfall davon) standardmäßig beim Leerzeichen trennt. Und dies verhindert man, wenn StrictDelimiter auf true gesetzt wird.
Mathias hat geschrieben:String.Splitt(...); ist das flexibelste, das ich kenne.
Aber vorsicht, wenn das Trennzeichen in doppelten Einführungszeichen eingeschlossen ist, weil man den so markierten Teilstring NICHT trennen möchte. Von den drei im folgenden Beispiel durchprobierten Varianten entspricht eigentlich nur das mit TStringList/DelimitedText meinen Vorstellungen:

Code: Alles auswählen

program Project1;
 
uses
  SysUtils, Classes;
 
const
  str = 'a;b;c d;"a;b"';
 
var
  sa: TStringArray;
  s: String;
  L: TStringList;
begin
  WriteLn('Split('';'')');
  sa := str.Split(';');
  for s in sa do
    WriteLn(s);
 
  WriteLn;
  WriteLn('Split('';'', ''"'', ''"'')');
  sa := str.Split(';', '"', '"');
  for s in sa do
    WriteLn(s);
 
  WriteLn;
  WriteLn('StringList.DelimitedText');
  L := TStringList.Create;
  L.Delimiter := ';';
  L.StrictDelimiter := true;
  L.DelimitedText := str;
  for s in L do
    WriteLn(s);
 
  ReadLn;
 
end. 

Warf
Beiträge: 2270
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: CommaText, nur Komma

Beitrag von Warf »

Mathias hat geschrieben:Dazu noch eine Frage, wieso hat CommaText mit mehreren Zeichen getrennt ?
Das hat schon ein bisschen Nützlichkeit, jetzt mal Abgesehen von den Quotes die wp_xyz schon angesprochen hat. Angenommen du hast eine standard CSV Datei, feste anzahl spalten, werte komma getrennt, Strings mit Anführungszeichen gekennzeichnet:

Code: Alles auswählen

sl.CommaText := CSVInhalt;
for line := 0 to sl.Length div AnzahlSpalten -1 do
  for column = 0 to AnzahlSpalten -1 do
    wert := sl[line * AnzahlSpalten + column];
Du hast mit einer einzigen Zeile eine komplette CSV datei geparsed.

Wobei meiner Meinung nach das eher der Spezialfall sein sollte und StrictDelimiter standardmäßig auf True stehen sollte

Antworten