Delphi e Split – Separação de string por delimitador
Já faz um tempo que precisei de uma função de fosse o mais rápida possivel e através de uma string e um delimitador passados como parâmetro me retornasse um vetor com os valos. Exemplo: “123|456|789″ tendo “|” como delimitador retornaria ["123", "456", "789"]
Uma das formas ja existentes na biblioteca interna do Delphi seria através de um TStringList:
function Split(const Str: string; Delimiter : Char): TStringList; begin Result := TStringList.Create; Result.LineBreak := Delimiter; Result.Text := Str; end;
Esta função pode ser usada da seguinte forma:
var
Ret : TStringList;
i: Integer;
begin
Ret := Split('123|456|789', '|');
for i := 0 to Ret.Count - 1 do
ShowMessage(Ret[i]);
Ret.Free;
end;
Nesse exemplo foi criando um objeto da classe TStringList (que é uma ótima classe para manipulação de strings no Delphi) e modificamos o caracter que denota uma quebra de linha para o nosso delimitador, porem uma abordagem mais prática e com melhor performance poderia seria feita da seguinte forma:
//Em interface
type
TStringArray = array of string;
function Split(const Str: string; Delimiter : Char; Max : integer = 0): TStringArray;
//Em implementation
function Split(const Str: string; Delimiter : Char; Max : integer = 0): TStringArray;
var
Size, i: integer;
begin
Size := 0;
SetLength(Result, 1);
Result[0] := '';
for i := 1 to Length(Str) do
begin
if Str[i] = Delimiter then
begin
Inc(Size);
if (Max <> 0) and (Size = Max) then
Break;
SetLength(Result, Size+1);
end
else
Result[Size] := Result[Size] + Str[i];
end;
end;
Como pode ser visto eu usei um tipo de dados previamente definido para retorno conforme explicado em outro post, ainda acrescentei um parâmetro para definir o tamanho máximo do vetor caso não me interesse todos valores. No mais esta função faz um laço que passa por todos caracteres da string onde verifica se o mesmo é o nosso delimitador. Caso negativo ela simplesmente continua concatenando o caracter à posição atual do vetor de retorno. Se o caracter atual é o delimitador ela aumenta o tamanho do nosso vetor e passar a posição atual no vetor (onde será feito a concatenação) para a nova posição criada, isso tudo condicionado a não ultrapassar o limite máximo do vetor recebido no terceiro parâmetro. Um exemplo de uso seria:
var
Ret : TStringArray;
i: Integer;
begin
Ret := Split('123|456|789', '|');
for i := 0 to Length(Ret) - 1 do
ShowMessage(Ret[i]);
end;
Esse exemplo é executado na metade do tempo do exemplo anterior além disso é mais prático por retornar um vetor e não um objeto que precisaria ser destruído através de um “Free”.
Thanks for an idea, you sparked at thought from a angle I hadn’t given thoguht to yet. Now lets see if I can do something with it.
Muito bom o seu post, consegui resolver um problema que estava tendo com execução de scripts em uma aplicação datasnap.
Grande abraço e parabéns.