Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Best way to remove the trailing comma (or whatever) from a string? 4

Status
Not open for further replies.

GriffMG

Programmer
Mar 4, 2002
6,288
1
38
FR
Curiosity getting the better of me... and knowing I won't be roasted by the current community... I hope. B-)

Assuming we have assembled a string like "1234,123,198,678," what are your favourite ways to remove the trailing comma?

Code:
m.STRING = LEFT(m.STRING,LEN(m.STRING)-1)

Is ok if you are confident there is a trailing comma... Mike recently hinted that PadR() might be useful.



Regards

Griff
Keep [Smile]ing

There are 10 kinds of people in the world, those who understand binary and those who don't.

I'm trying to cut down on the use of shrieks (exclamation marks), I'm told they are !good for you.

There is no place like G28 X0 Y0 Z0
 
Mike recently hinted that PadR() might be useful

Did I? If so, that was clearly a mistake. The function is RTRIM():

[tt]
lcString = RTRIM(lcString, ",")[/tt]

And no harm is done if it happens that there is no trailing comma.

(I have now corrected thread184-1819024.)

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
That is pretty neat, I was not aware of the option to include one or more characters.

Regards

Griff
Keep [Smile]ing

There are 10 kinds of people in the world, those who understand binary and those who don't.

I'm trying to cut down on the use of shrieks (exclamation marks), I'm told they are !good for you.

There is no place like G28 X0 Y0 Z0
 
Hi,

RTRIM() is the way to go

you may even specify all the characters you want to be removed from the right edge

lcStr = "2345,6667,88.,bab"

? RTRIM(lcStr, ".",",","a","b")

hth

MarK
 
I was not aware of the option to include one or more characters.

That option was only introduced in VFP 9.0. Before that, you could only use the function to remove trailing spaces.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
OK, here's something else to wrap your brains around.

Suppose you have one or more comma inside a string, perhaps like this:

[tt]HELLO,,,WORLD,FROM,,,,TEK-TIPS[/tt]

You want to eliminate all those commas, replacing each substring of commas with a single space, like so:

[tt]HELLO WORLD FROM TEK-TIPS[/tt]

How would you go about that with the minimum amount of code?

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Help says RTRIM() is identical to TRIM()

That's right. The reason is historical. Back in dBASE days, they never thought we would ever want to trim the left-most spaces. So we had just plain TRIM(), which trimmed the right-most spaces. When LTRIM() was later introduced, they added RTRIM() to balance things out, as it were. But of course they kept the old TRIM(), so as not to break compatibility.

Personally, I always use RTRIM() in preference to TRIM() for the simple reason that it is more explicit. I expect most other developers do too.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Well, I would divide this into 3 camps:

1. Build the string with the necessary commas only
2. Use comma prefixed before each item and finally use SUBSTR from the second position.
3. Add items with ccomma suffix and finally remove the surplus comma with LEFT() or RTRI/TRIM.

Assume there is a dbf or curssro alias items with an item field that's varchar and so has trimmed items (no trailing spaces as you have with a normal char field).


1. with IIF
Code:
Local lcCSV
lcCSV=''
Select items
scan
   lcCSV = m.lcCSV+IIF(lcCSV=='','',',')+items.item
endscan

2. prefix and SUBSTR
Code:
Local lcCSV
lcCSV=''
Select items
scan
   lcCSV = m.lcCSV+','+items.item
endscan
lcCSV = Substr(m.lcCSV,2)

3. suffix and TRIM
Code:
Local lcCSV
lcCSV=''
Select items
scan
   lcCSV = lcCSV+items.item+','
endscan
lcCSV = RTRIM(m.lcCSV,',')

And all of them have their negative point.
1. An IIF for every item
2. and 3: A final string operation.

But it's also pointless to rant about this necessary last operation in case 2 and 3, as every item you append with the assignment lcCSV = lcCSV + does nneed to allocate enough memeory for the overall string, and copies over lcCSV plus the item into it. VFP has no thing like C#'s stringbuilder class. And though VFP is programmed in C++ it also has no pointer to do tricks with, at least you don't have hands on it within VFP itself. There also isn't a function like PHPs implode().

There are surely more ways to do it
4. like 1, but without IIF:
Code:
Local lcCSV, lcSeparator
Store '' To lcCSV, lcSeparator
Select items
scan
   lcCSV = m.lcCSV+lcSeparator+items.item
   lcSeprator = ','
endscan
Now there's no IIF, but an assignment that would be suffiient, if it's done once instead of every iteration

5. like 1 but through special handling of first element
Code:
Local lcCSV
Select items
Go Top
lcCSV = items.item
Skip 1
Scan Rest
   lcCSV = m.lcCSV+','+items.item
Endscan

Now you can play with these and special cases like extremely many items or no items at all, etc. etc.

But you can't tell me that you can't think of any way on your own, at least to create the string with a surplus comma at the start or end. And then it's really just a short visitation of the help to look up how to get substrings, which functions exist for that, like LEFT, RIGHT, SUBSTR, or how you can use TRIM/RTRIM/LTRIM/ALLTRIM. Also ALLTRIM allows specifying other characters to trim away than whitespace.

It does really not play any mentionable role to do things the one or other way. If you have extremely many elements it would turn out to be better to create partial lists and concatenate them as a last step. If you have 1 million elements you would make 999.999 copies in average half the string length, and that would hurt the performance, but it would be a problem no matter which of the three major methods you choose. And the last step to remove the comma will never be a major part of the operation.

Chriss
 
I might do this, but I am sure there is an array function too

Code:
CLEAR

? CLEARSTRING("HELLO,,,WORLD,FROM,,,,,,,,,TEK-TIPS",",")

FUNCTION CLEARSTRING
	PARAMETERS m.STRING,m.STRDELIM
	PRIVATE m.STRING,m.STRDELIM,m.STRING2,m.MAXWORDS,m.INDEX
	m.MAXWORDS = GETWORDCOUNT(m.STRING,m.STRDELIM)
	m.STRING2 = ""
	FOR m.INDEX = 1 TO m.MAXWORDS
		m.STRING2 = m.STRING2+GETWORDNUM(m.STRING,m.INDEX,m.STRDELIM)+" "
	NEXT
	RETURN(RTRIM(m.STRING2))



Regards

Griff
Keep [Smile]ing

There are 10 kinds of people in the world, those who understand binary and those who don't.

I'm trying to cut down on the use of shrieks (exclamation marks), I'm told they are !good for you.

There is no place like G28 X0 Y0 Z0
 
Mike,

about your task to fix a string like "HELLO,,,WORLD,FROM,,,,TEK-TIPS".
I guess you think about the foxtools.fll, which has that function for it:

Code:
lcCSV = "HELLO,,,WORLD,FROM,,,,TEK-TIPS"

Set Library To Home()+"foxtools.fll"
lcCSV = Reduce(lcCSV,',')

? lcCSV

It's replaceing any number of commas with one space, though, so at the end you get [tt]HELLO WORLD FROM TEK-TIPS[/tt].

Now it would depend on whether single items (i.e two words or more, like full names) can contain spaces. If not, you could now replace every space with a comma:
Code:
lcCSV = "HELLO,,,WORLD,FROM,,,,TEK-TIPS"

Set Library To Home()+"foxtools.fll"
lcCSV = Chrtran(Reduce(lcCSV,','),' ',',')

? lcCSV

Well, if you have spaces within items, what would work is first replacing them with something else to protect them as is.
Code:
lcCSV = "Mike Lewis,,,Chirs Miller,Steve Meyerson,,,,TEK TIPS"

Set Library To Home()+"foxtools.fll"
lcCSV = Chrtran(Reduce(ChrTran(lcCSV,' ',Chr(255)),','),' '+Chr(255),', ')

?lcCSV
And the only thing to ensure as prerequisite for this to not break anything is to have no CHR(255) in your items. Thats ÿ and also a letter, so perhaps use some other character as temporary space replacement, like chr(7), which is the ANSI character for playing "ding.wav" and so usually is not within any string items.


Chriss
 
How about this ...

Code:
s="HELLO,,,WORLD,FROM,,,,,,,,,TEK-TIPS"
DO WHILE AT(",,",s)>0
  s=STRTRAN(s,",,",",")
ENDDO
? s
 
Oops, I didn't notice that we wanted ALL commas gone, here is the updated code:

Code:
s="HELLO,,,WORLD,FROM,,,,,,,,,TEK-TIPS"
DO WHILE AT(",,",s)>0
  s=STRTRAN(s,",,",",")
ENDDO
s=STRTRAN(s,","," ")
? s
 
jwilson said:
I didn't notice that we wanted ALL commas gone, here is the updated code:

I'm guilty of the same misunderstanding. Aa the main topic was comma separated lists.
Indeed Reduce() of foxtools does that and wouldn't need a while loop. It would help to have a Reduce function in which you could also specify what character you want to end up with, too. So you could decide to get a string with single spaces or a comma separated list or whatever you want.

Chriss
 
How about this:
Code:
t="HELLO,,,WORLD,FROM,,,,TEK-TIPS"
?t
HELLO,,,WORLD,FROM,,,,TEK-TIPS
?STRTRAN(STRTRAN(STRTRAN(t,",,",","),",,",","),","," ")
HELLO WORLD FROM TEK-TIPS
Of course, more "," would require additional STRTRAN ...

I came looking for another answer and got pulled into Mike's exercise, DOH!

msc [wink]
 
Some good solutions there. But there is a simpler way. In fact, Chris hinted at what I had in mind:

Code:
SET LIBRARY TO "foxtools.fll"
? REDUCE("HELLO,,,WORLD,FROM,,,,TEK-TIPS", [highlight #FCE94F]","[/highlight])

EDIT: Sorry, I missed out the second parameter to REDUCE(). I have now added it - see highlight).

Mike


__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Mike Lewis,

you forgot to ask REDUCE to reduce one or multiple commas to spaces. The REDUCE as you posted it (REDUCE("HELLO,,,WORLD,FROM,,,,TEK-TIPS")) does not remove anything.
I see you corrected your post.

Using REDDUCE for other characters also has its downside, as already said:
Code:
? REDUCE("Ssssnailssss","Ss")
This outputs " nail ".

If you'd like to get "Snails" as a result you'd need to replace the first space with "S" and the last one with "s".
More generally said, if you use REDUCE to reduce other characters than whitespace characters and reduce multiple characters, it becomes harder to reduce them to single instances of themselves, as REDUCE always reduces what it reduces to single spaces. So its main intent is to remove surplus whitespace, as could be found in HTML, for example, or in source code. Though in case of source code reduce should make a difference between spaces in string delimiters vs the rest of the code, where any number of spaces have the same meaning as a single space.

Chriss.
 
Nice - did not realize REDUCE was a function. I need to read more

thanks!
 
REDUCE only can be used once you SET LIBRARY TO FOXTOOLS.FLL. Most functions of this library are already part of VFP or very similarly integrated into VFP. One of the few useful things of the FLL is Reduce, and some functions regarding the Windows clipboard, so you can work with more than just _CLIPTEXT.

Chriss
 
Thanks, Chris. I should have specified a comma as the second parameter to REDUCE(). I have now corrected it - see above.

Of course, you can remove any character in this way, not just commas. You can also specify multiple characters in the second parameter, in which case they are treated independently, not as a single multi-character string.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top