function RemoveCommas(aStr: String): String;
begin
// Remove Comma(s) from String
// e.g. 1,000,000.00 will now read 1000000.00
while Pos(',', aStr) > 0 do
Delete(aStr, Pos(',', AStr), 1);
Result := aStr;
end;
I could only come up with the above.
Just curious.
Martin Kelly
function RemoveCommas(const aStr: String): String;
var cnt,len: integer;
pch,pchr: pChar;
begin
len := length(aStr);
SetLength(Result,len);
if len = 0 then exit;
Cnt := 0;
pCh := @aStr[1];
pChr := @Result[1];
For i := 1 to len do begin
if pCh^ <> ',' then begin
pChr^ := pCh^;
inc(Cnt);
inc(pChr);
end;
inc(pCh);
end;
SetLength(Result,Cnt);
end
is definitely more effective.
--
Roman
(please remove 'stopspam' in header when replying)
mail: in...@rksolution.cz
URL: www.rksolution.cz
Martin Kelly píše ve zprávě <7fkdd2$4d...@forums.borland.com>.
In D4 you could use the new StringReplace function:
type
TReplaceFlags = set of (rfReplaceAll, rfIgnoreCase);
function StringReplace(const S, OldPattern, NewPattern: string; Flags: TReplaceFlags): string;
efg
_________________________________
efg's Computer Lab: www.efg2.com/lab
Delphi Books: www.efg2.com/lab/TechBooks/Delphi.htm
Earl F. Glynn E-Mail: Earl...@att.net
Overland Park, KS USA
function RemoveCommas(aStr: String): String;
begin
// Remove Comma(s) from String
// e.g. 1,000,000.00 will now read 1000000.00
while Pos(',', aStr) > 0 do
Delete(aStr, Pos(',', AStr), 1);
Result := aStr;
end;
>>
You're right about the inefficiency. The true answer is to go get the free
HyperString from http://efd.home.mindspring.com/tools.htm (source is $39).
Otherwise, I'd like to correct Roman's blind infatuation with pointers, and
so slow too<g> --
Function stripChar (s: string; c: char): string;
(*Returns s minus all occurrences of c*)
Var
js: integer; //current index into s
js0: integer; //index of first uncopied char in s
jr: integer; //first unused position in result
Begin
setLength(result, length(s));
js0 := 1;
jr := 1;
for js := 1 to length(s) do if (s[js] = c) then begin
move(s[js0], result[jr], js-js0);
inc(jr, js-js0);
js0 := js + 1;
end;
move(s[js0], result[jr], length(s) + 1 - js0);
setLength(result, jr + length(s) - js0);
End;
PhR
I'll try your code.
Thanks.
> You're right about the inefficiency. The true answer is to go get the free
> HyperString from http://efd.home.mindspring.com/tools.htm (source is
$39).
> Otherwise, I'd like to correct Roman's blind infatuation with pointers,
and
> so slow too<g> --
>
> Function stripChar (s: string; c: char): string;
> (*Returns s minus all occurrences of c*)
> Var
> js: integer; file://current index into s
> js0: integer; file://index of first uncopied char in s
> jr: integer; file://first unused position in result
Better than that. Don't tell Roman, but for shortish strings with one or two
commas, I think your thing is faster. But HyperString is best.
PhR
Martin Kelly wrote:
>
> Is there a more efficient way of removing the comma characters from a
> string?
>
> function RemoveCommas(aStr: String): String;
> begin
> // Remove Comma(s) from String
> // e.g. 1,000,000.00 will now read 1000000.00
> while Pos(',', aStr) > 0 do
> Delete(aStr, Pos(',', AStr), 1);
> Result := aStr;
> end;
>
> I could only come up with the above.
>
> Just curious.
>
> Martin Kelly
I dont like to call Pos() twice per loop: perhaps someone likes this
function RemoveCommas(aStr: String): String;
VAR
p:integer;
BEGIN
p:=Pos(',',aStr);
WHILE (0<p) DO BEGIN
Delete(aStr,p,1);
p:=Pos(',',aStr);
END;
Result := aStr;
END;
Glynn - Uses builtin "StringReplace"
Ranger - Indexed copy of characters between strings
Kelly - used "Pos" and "Delete"
Walter - Same as Kelly,except used only one "Pos"
HyperString - not actually posted - code follows
Krejci - used pchar copy routine
Timings in seconds were as follows:
Krejci .31 .006
Hyper .54 .008
Walter 1.08 5.98
Kelly 1.31 10.19
Ranger 6.10 33.12
Glynn 6.12 33.28
It appears that the original answer is by far the quickest, if not
necessarily the "best code". It certainly depends on how much it is
used which one you might want in your code. StringReplace is
certainly the cleanest but could take minutes instead of fractions of
a second for a large file.
The Hyperstring routine performed almost as well as the best, and
certainly is cleaner, if not exactly intuitive
function RemoveCommas_Hyper(const aStr:String):String;
begin
Result:=aStr;
SetLength(Result,DeleteC(Result,','));
end;
I have just downloaded Hyperstring, so have no experience with it.
Perhaps there is an even better way to do this.
Phil
Timings in seconds were as follows:
Krejci .31 .006
Hyper .54 .008
Walter 1.08 5.98
Kelly 1.31 10.19
Ranger 6.10 33.12
Glynn 6.12 33.28
>>
Phil, thanks for the work and report.
I'm saddened to see that Roman's pointer-infatuated solution was faster than
mine. But I'm rather struck with disbelief to find pos+delete also several
times faster than mine. There's something wrong. If you used the right code
(stripChar), the only thing I can see is that Roman refers constantly to the
result string, and that this may produce much healthier cache management.
<<
function RemoveCommas_Hyper(const aStr:String):String;
begin
Result:=aStr;
SetLength(Result,DeleteC(Result,','));
end;
>>
Could be simplified to --
function RemoveCommas_Hyper(const aStr:String):String;
begin
Result:=aStr;
DeleteC(Result,','));
end;
PhR
> function RemoveCommas_Hyper(const aStr:String):String;
> begin
> Result:=aStr;
> SetLength(Result,DeleteC(Result,','));
> end;
> >>
>
> Could be simplified to --
>
> function RemoveCommas_Hyper(const aStr:String):String;
> begin
> Result:=aStr;
> DeleteC(Result,','));
> end;
>
Not quite. DeleteC only does a "pseudo-delete". In other words, it provides
the appearance of a deletion by shifting characters and space filling at the end
of string. If absolutely necessary, the fill spaces at the end can be manually
removed using SetLength() as in the first example above. Depending on the
application, this may not be necessary. For example, if the string is only
going to be used for display, a few extra spaces at the end may not make any
difference and the overhead of string re-allocation can be avoided.
For better performance, eliminate the overhead of the special function and code
it directly in-line. For example, instead of:
X := RemoveCommas_Hyper(Y);
use this:
X := Y;
SetLength(X,DeleteC(X,',')); //remove commas
--
Ernie Deel, EFD Systems
-------------------------------------------------
The future is just like the past, only more expensive.
Phil obviously read the docs better than I did -- he got to the Note which
is the main text! Imho, Ernie, this is carrying the need for speed a bit
far -- "delete" is already a standard procedure, and it does mean "remove
and shorten". I think the case where your result can be used as-is is the
exception, not the rule.
<<
SetLength(X,DeleteC(X,',')); //remove commas
>>
That's an argument. But you know how popular this C-type coding is with
Delphi users.
PhR
> Imho, Ernie, this is carrying the need for speed a bit
> far -- "delete" is already a standard procedure, and it does mean "remove
> and shorten".
Point taken.
This is admittedly somewhat controversial. Some users like it, others don't.
Now that it's done, it can't be undone without breaking existing code.
No. It's a naming problem, and done is done.
PhR
|I'm saddened to see that Roman's pointer-infatuated solution was faster than
|mine. But I'm rather struck with disbelief to find pos+delete also several
|times faster than mine. There's something wrong. If you used the right code
Something wrong indeed! I called Glynn's code twice - Copy and paste
bug. Sorry about that. I should have noticed the little blue dots
missing from your routine. I made one minor change to your code - the
"," was hard-coded, rather than passed, to make all functions the
same.
The corrected timings follow:
Timings in seconds were as follows:
Krejci .31 .006
Hyper .54 .008
Ranger .86 .010
Walter 1.08 5.98
Kelly 1.31 10.19
Glynn 6.12 33.28
Phil
Thanks for the fix, but all I want is to beat Roman! Seriously, it still is
odd that HyperString, in asm, should be slower than Roman's code. It's as if
doing batch moves was slower than moving chars one at a time.
If you have the patience, try the following. It's my solution, but using
pointers like Roman does --
Function stripComma (s: string): string;
(*Returns s minus all occurrences of commas*)
Var
ps: pChar; //current char in s
ps0: pChar; //first uncopied char in s
pr: pChar; //first unused position in result
n: integer;
Begin
setLength(result, length(s));
ps := pChar(s);
ps0 := ps;
pr := pChar(result);
for n := 1 to length(s) do begin
if (ps^ = ',') then begin
move(ps0^, pr^, ps-ps0);
inc(pr, ps-ps0);
ps0 := ps + 1;
end;
inc(ps);
end;
move(ps0^, pr^, ps - ps0);
setLength(result, pr - pChar(result) + ps - ps0);
End;
PhR
The code I posted will strip any one char from a string. If you used
directly, I don't think you'd have a problem. The "digit grouping symbol" is
defined in SysUtils as "thousandSeparator", and initialized from local
settings. So, things should work if you simply did --
strToInt(stripChar(str, thousandSeparator));
I think your exception is raised because you've hard-coded the dot in, so
strToInt gets a string with commas left in it, and raises the exception.
PhR
The additional overhead of the special function call is the most likely cause.
Roman's routine is being called direct whereas the HyperString routines are not.
Each
additional level of indirection adds overhead.
This function is used to show the file size (with comma or dot) into
listview after retrieving using TSearchRec.
Function CommaStr(N : LongInt) : String;
Var
S : String;
R : Single;
Begin
R := N;
FmtStr(S, '%.0n', [r]);
Result := S;
End;
I use your function to calculate the size of multiple files so that it
returns integer instead of string.
SetLength(Temp, Length(Str));
j := 1;
k := 1;
For i := 1 To Length(Str) Do
If Str[i] = '.' Then
Begin
Move(Str[j], Temp[k], i - j);
Inc(k, i - j);
j := i + 1;
End;
Move(Str[j], Temp[k], Length(Str) + 1 - j);
SetLength(Temp, k + Length(Str) - j);
Result := StrToInt(Temp)
If the digit grouping symbol (Regional Settings) is '.' (dot), it works.
But if it is ',' (comma), it raises an exception. So I'd like to ask you
if there is another way to remove dot (or comma ->depends on the digit
grouping symbol)?
Is it possible using FmtStr?
Thanks in advance.
Regards,
Wasis
Philippe Ranger wrote:
> Function stripChar (s: string; c: char): string;
> (*Returns s minus all occurrences of c*)
> Var
> js: integer; //current index into s
> js0: integer; //index of first uncopied char in s
> jr: integer; //first unused position in result
> Begin
> setLength(result, length(s));
> js0 := 1;
> jr := 1;
> for js := 1 to length(s) do if (s[js] = c) then begin
> move(s[js0], result[jr], js-js0);
> inc(jr, js-js0);
> js0 := js + 1;
> end;
> move(s[js0], result[jr], length(s) + 1 - js0);
> setLength(result, jr + length(s) - js0);
> End;
>
> PhR
|<<Phil:
|Krejci .31 .006
|Hyper .54 .008
|Ranger .86 .010
|>>
|Thanks for the fix, but all I want is to beat Roman! Seriously, it still is
|odd that HyperString, in asm, should be slower than Roman's code. It's as if
|doing batch moves was slower than moving chars one at a time.
|If you have the patience, try the following. It's my solution, but using
|pointers like Roman does --
Ranger2 .45 .005
Second-fastest for short string, fastest (slightly) for long string.
We're at the point where code placement could be the deciding factor.
A function that just copies input to output times:
null .05 .004
function RemoveCommas_Null(const aStr: String): String;
begin
Result:=aStr;
end;
Phil
Second-fastest for short string, fastest (slightly) for long string.
We're at the point where code placement could be the deciding factor.
A function that just copies input to output times:
>>
You're a pearl, Phil. What do we do to keep you around?
This shows that Roman was dead right that pointer access is likely to be
faster. Drat it! Indexed access is both simpler and clearer.
It also shows that using Move only saves rather than wastes time when the
block approaches 14 bytes. A randomized comma placement would give more
accurate figures, but anyhow... I still figure Roman's code (which is
clearly simpler) wins out from better cache (or register?) optimization.
PhR