10. november 2003 - 18:53Der er
3 kommentarer og 1 løsning
StringList's DelimitedText er blevet tosset
jeg har en meget simpel tekst, som jeg vil splitte op med StringList's DelimitedText funktion. Det virker nu også meget godt med fx Delimiter := ';' eller Delimiter := #9 (tab) men!!!
Den spliter sørmer også ved alm. mellemrum!! hva skal de nu ligne?? hvis jeg har teksten: "dav med dig;du er en gammel nar" og sætter delimiter til ; så splitterne den:
dav med dig du er en gammel nar
går ud fra det er synligt hvad problemet er!! men hvordan løser jeg det?
Der bliver investeret massivt i AI. Teknologien er mere tilgængelig end nogensinde, og ambitionerne er høje. Alligevel oplever mange virksomheder, at resultaterne udebliver.
Jeg har sakset nedenstående fra en nyhedsgruppe på nettet:
It's not a bug - it's noted in the help file. Still a PITA, so here's my personal replacement (public domain, as-is):
{ procedure CSVParse
Parses a line from a CSV file into distinct fields. <sInput> is the line of CSV data. <Fields> is a TStrings/TStringList variable that will hold the results. The list will be cleared before use. <AQual> is the string qualifier and defaults to a double-quote ("). Qualifiers will be stripped from fields and any literals within the field will be undoubled. <ADelim> is the field delimiter and defaults to a comma (,). }
procedure CSVParse(const sInput: String; Fields: TStrings; const AQual: String = '"'; const ADelim: String = ','); var sWork, sField, sChar: String; i, w: Integer; begin Fields.Clear; sWork := sInput; while Length(sWork) > 0 do begin // Is this field surrounded by the qualifier? if sWork[1] = AQual then begin // Find the next instance of the delimiter preceeded by a non-literal // qualifier. If not present, find the next qualifier and/or EOL. sWork := Copy(sWork, 2, MaxInt); i := Pos(AQual, sWork); if i < 1 then i := 1; sField := Copy(sWork, 1, i - 1); w := Length(sWork); while i <= w do begin sChar := sWork[i]; if sChar = AQual then begin if i = w then begin // EOL. We're done, but discard this trailing qualifier. Inc(i); break; end else if sWork[i + 1] = ADelim then begin // Qualifier followed by a delimiter. Done! Inc(i, 2); break; end else if sWork[i + 1] = AQual then begin // It's a literal when followed by another qualifier. Skip ahead. Inc(i); end; end; sField := sField + sChar; Inc(i); end; sWork := Copy(sWork, i, MaxInt); end else begin // Not a qualified field - just find the next delimiter or EOL: i := Pos(ADelim, sWork); if i > 0 then begin sField := Copy(sWork, 1, i - 1); sWork := Copy(sWork, i + 1, MaxInt); end else begin // EOL sField := sWork; sWork := ''; end; end; // Add this field to the TStrings/TStringList: Fields.Add(sField); end; // while Length(sWork) > 0
// If the line ends with a delimiter, add a blank field to the list: i := Length(sInput); if (i > 0) and (sInput[i] = ADelim) then Fields.Add('');
end;
Synes godt om
Slettet bruger
10. november 2003 - 19:26#2
Du kan jo også erstatte mellemrummene i sætningen med et andet tegn:
var Str: String; L: TStringList; begin L := TStringList.Create; Str := AnsiReplaceStr('dav med dig;du er en gammel nar', ' ',Chr(255)); L.Delimiter := ';'; L.DelimitedText := Str; L.Text := AnsiReplaceStr( L.Text, Chr(255), ' '); end;
Når man nu er gået så vidt, kan det jo bare ende helt med stringreplace:
var Str: String; st: TStringList; begin Str := 'dav med dig;du er en gammel nar'; st := TStringList.Create; st.text := stringreplace(Str, ';', #13#10, [rfreplaceall]); showmessage(st.text); st.free; end;
dkn må siges at have lavet den nemmeste løsning. det er ikke alverden tekst der skal parses, så at metoden går hurtigere vil ikke vise den store forskel.
tak til jer alle sammen
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.