大家讨论一下分割字符串的效率问题,高人请进……

wanwangzhiwang 2003-10-31 04:03:01
最近在项目中遇到分割字符串的问题,因为数据量比较大,大概有5万多条,每条字符串用特定的字符隔开。

开始用copy来分割,发现效率奇低,后来又用Pchar配合汇编分割,效率有所提高,但还是不是很如意。

不知道各位大侠有何高见……

附上用copy的方法(用pchar配合汇编的方法因为大部分是公司牛人写的,不便公开,请见谅)

function SplitString(const source, ch: string): TResultArray;

var

temp: string;

i: integer;

begin

temp := source;

i := pos(ch, source);

while i <> 0 do

begin

SetLength(Result, Length(Result) + 1);

Result[Length(Result) - 1] := copy(temp, 0, i - 1);

delete(temp, 1, i);

i := pos(ch, temp);

end;

SetLength(Result, Length(Result) + 1);

Result[Length(Result)-1] := Temp;

end;



...全文
91 28 打赏 收藏 转发到动态 举报
写回复
用AI写文章
28 条回复
切换为时间正序
请发表友善的回复…
发表回复
Seahilly 2003-11-14
  • 打赏
  • 举报
回复
你再试试RTL中Windows下的字符串比较函数,替代Pos函数:

function CompareStringA(Locale: LCID; dwCmpFlags: DWORD; lpString1: PAnsiChar;
cchCount1: Integer; lpString2: PAnsiChar; cchCount2: Integer): Integer; stdcall;
function CompareStringW(Locale: LCID; dwCmpFlags: DWORD; lpString1: PWideChar;
cchCount1: Integer; lpString2: PWideChar; cchCount2: Integer): Integer; stdcall;
function CompareString(Locale: LCID; dwCmpFlags: DWORD; lpString1: PChar;
cchCount1: Integer; lpString2: PChar; cchCount2: Integer): Integer; stdcall;
wanwangzhiwang 2003-11-11
  • 打赏
  • 举报
回复
fengjn(颗粒)

再贴一次吧,让大家都见识见识
wanwangzhiwang 2003-11-11
  • 打赏
  • 举报
回复
Seahilly(小峰)
你的方法虽然有所改进,可是效率决不是最高的,前面有位高人不是说过吗:“

因为在Delphi中,COPY、Pos 和 Replace等都是基于内存复制的,也就是说所有参数内容都要生成一个副本,如果字符串的长度巨大,则副本的大小就可想而知了
而字符串分割需要N多次的Copy、Pos之类的操作,所以速度就自然大打折扣。”
庆祝0101 2003-11-10
  • 打赏
  • 举报
回复
ben
yudehui 2003-11-10
  • 打赏
  • 举报
回复
我虚心
我不懂
我学习
来顶一下吧!
vuen 2003-11-10
  • 打赏
  • 举报
回复
学习,顶!
saien 2003-11-10
  • 打赏
  • 举报
回复
Seahilly 2003-11-10
  • 打赏
  • 举报
回复
对不起,错了一句:
target[i]:=Char(0); //将间隔字符强制设置成为一个结束符
Seahilly 2003-11-10
  • 打赏
  • 举报
回复
改进你的函数:
基本思路是先将字符串放入字符数组中,然后根据特殊间隔字符计算相对位置,再将相对位置以PChar数组的形式返回。以下函数只是个思路,但是pos函数的第二个参数可以是PChar。

var TcharArray:Array[0..MaxLen] of Char;
function SplitString(const source, ch: string,var target:TcharArray): TPcharArray;

var

i,j,k,: integer;

begin

ZeroMemory(@target,Sizeof(target));
MoveMemory(@target,PChar(source),Length(source));


j:=0
i := pos(ch, source);
k:=0;

while i <> 0 do

begin

Result[k] := PChar(@target[j]);
target[j]:=Char(0); //将间隔字符强制设置成为一个结束符
k:=k+1;
j:=i;
i := pos(ch, PChar(@target[i+1]));

end;

Result[k] := PChar(@target[j]);
k:=k+1;
j:=i;

end;
fengjn 2003-11-10
  • 打赏
  • 举报
回复
我记得我在一个帖子的回复里说个这个,我用的扫描的方法,有点类似有穷自动机。效率大概是使用strings的10被左右
yayx 2003-11-10
  • 打赏
  • 举报
回复
function ExtractStrings(Separators, WhiteSpace: TSysCharSet; Content: PChar;
Strings: TStrings): Integer;
var
Head, Tail: PChar;
EOS, InQuote: Boolean;
QuoteChar: Char;
Item: string;
begin
Result := 0;
if (Content = nil) or (Content^=#0) or (Strings = nil) then Exit;
Tail := Content;
InQuote := False;
QuoteChar := #0;
Strings.BeginUpdate;
try
repeat
while Tail^ in WhiteSpace + [#13, #10] do Inc(Tail);
Head := Tail;
while True do
begin
while (InQuote and not (Tail^ in ['''', '"', #0])) or
not (Tail^ in Separators + [#0, #13, #10, '''', '"']) do Inc(Tail);
if Tail^ in ['''', '"'] then
begin
if (QuoteChar <> #0) and (QuoteChar = Tail^) then
QuoteChar := #0
else QuoteChar := Tail^;
InQuote := QuoteChar <> #0;
Inc(Tail);
end else Break;
end;
EOS := Tail^ = #0;
if (Head <> Tail) and (Head^ <> #0) then
begin
if Strings <> nil then
begin
SetString(Item, Head, Tail - Head);
Strings.Add(Item);
end;
Inc(Result);
end;
Inc(Tail);
until EOS;
finally
Strings.EndUpdate;
end;
end;
yayx 2003-11-10
  • 打赏
  • 举报
回复
现成的函数

ExtractStrings function


Fills a string list with substrings parsed from a delimited list.

Unit

Classes

Category

string handling routines (null-terminated)

function ExtractStrings(Separators, WhiteSpace: TSysCharSet; Content: PChar; Strings: TStrings): Integer;

Description

Use ExtractStrings to fill a string list with the substrings of the null-terminated string specified by Content.

Separators is a set of characters that are used as delimiters, separating the substrings. Carriage returns, newline characters, and quote characters (single or double) are always treated as separators. Separators are ignored when inside a quoted string until the final end quote. (Note that quoted characters can appear in a quoted string if the quote character is doubled.)

WhiteSpace is a set of characters to be ignored when parsing Content if they occur at the beginning of a string.

Content is the null-terminated string to parse into substrings.

Strings is a string list to which all substrings parsed from Content are added. The string list is not cleared by ExtractStrings, so any strings already in the string list are preserved.

ExtractStrings returns the number of strings added to the Strings parameter.

Note: ExtractStrings does not add empty strings to the list.
wellgsy 2003-11-10
  • 打赏
  • 举报
回复
不用pos和copy函数,用一次循环比较完会快些
tw829 2003-11-10
  • 打赏
  • 举报
回复
study
huzi 2003-11-10
  • 打赏
  • 举报
回复
我是这样做的:

建立一个目标字符数组,
同时将原串当作字符数组看.
对原串进行逐字扫描,
  如果不是分隔符,就放到目标字符数组中
  如果是分隔符,将目标字符数组中的内容放到一个字符串中
继续对原串扫描,直到结束

因为在Delphi中,COPY、Pos 和 Replace等都是基于内存复制的,也就是说所有参数内容都要生成一个副本,如果字符串的长度巨大,则副本的大小就可想而知了
而字符串分割需要N多次的Copy、Pos之类的操作,所以速度就自然大打折扣。
wanwangzhiwang 2003-11-10
  • 打赏
  • 举报
回复
今天发现原来计算速度慢的原因不是切割字符串,而是切割后的某些操作

虚惊一场

不过这次讨论我觉得还是没有实质性的进展,楼上各位的方法都集中在tstringlist上,难道就没有更好的方法吗?
saien 2003-11-06
  • 打赏
  • 举报
回复
up
wanwangzhiwang 2003-11-06
  • 打赏
  • 举报
回复
除了tstringlist,还有别的方法吗?
huojiehai 2003-11-02
  • 打赏
  • 举报
回复
既然有牛人为什么还搞不定!
如果不是“,”(是的话用 outer2000(天外流星) 兄的方法)分隔,用delphi6,7的话

用tstringlist的Delimiter和DelimitedText配合试试
123hui 2003-11-02
  • 打赏
  • 举报
回复

多线程!!!!!!!!!!!!!!!!!!
加载更多回复(8)

5,388

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧