Plateforme Level Extreme
Abonnement
Profil corporatif
Produits & Services
Support
Légal
English
Remove excessive spaces in string
Message
De
24/07/2009 19:40:22
 
 
À
24/07/2009 17:41:55
Information générale
Forum:
Visual FoxPro
Catégorie:
Codage, syntaxe et commandes
Versions des environnements
Visual FoxPro:
VFP 8 SP1
OS:
Windows XP SP2
Network:
Windows 2008 Server
Database:
Visual FoxPro
Application:
Desktop
Divers
Thread ID:
01414370
Message ID:
01414412
Vues:
70
>>>I have a string that contains many spaces. For example
>>>
>>>
x = 'test1    test2 test3    test4  test5       test6'
>>>
>>>how can I format the string to contain only one space between the 'test' values. For example how do get it to do the following:
>>>
>>>
x = 'test1 test2 test3 test4 test5 test6'
>>>
>>>I thought about using strtran() command but I don't it works the way I want it too.
>>
>>Naomi's answer is simple and elegant.
>>
>>You can do the same thing with successive or nested STRTRAN() calls e.g.
>>
>>x = 'test1    test2 test3    test4  test5       test6'
>>
>>x = STRTRAN( x, SPACE( 8 ), SPACE( 1 ) )
>>x = STRTRAN( x, SPACE( 8 ), SPACE( 1 ) )
>>x = STRTRAN( x, SPACE( 4 ), SPACE( 1 ) )
>>x = STRTRAN( x, SPACE( 4 ), SPACE( 1 ) )
>>x = STRTRAN( x, SPACE( 2 ), SPACE( 1 ) )
>>x = STRTRAN( x, SPACE( 2 ), SPACE( 1 ) )
>>
>>?x
>>* Above handles up to 64 spaces ( 8 x 8 )
>>* Adding 2 more lines at the top with SPACE( 16 ) would increase capacity to 256 spaces ( 16 x 16 )
>>* etc.
>>
>>* I suspect the FoxTools REDUCE() function may be a recursive implementation of the above
>>
>
>If your going to do that you should just put it in a loop
>
>x = 'test1    test2 test3    test4  test5       test6'
>DO WHILE SPACE(2) $ x
>   x = STRTRAN(x, '  ', ' ')
>ENDDO
>
It turns out the technique I wrote above is more "powerful" than I originally thought:

- as shown above, the code (up to SPACE( 8 )) handles spaces up to 4096 long (2^12). Breaks on 4097
- if it's extended with 2 extra lines at the top (with SPACE( 16 )) it handles spaces up to 2^20 long (breaks on 2^20 + 1)
- having just the bottom 4 lines handles spaces up to 64 long (breaks on 65)

So, we have 3 different ways to handle this:
- FoxTools REDUCE function (Reduce_FoxTools)
- My sequential technique (Reduce_Sequential)
- Your looping technique (Reduce_Loop)

Here's some code to test performance:
* ReduceTest.PRG

CLEAR

SET TALK OFF
SET DECIMALS TO 3

SET LIBRARY TO ( HOME( ) + "FoxTools.FLL" ) ADDITIVE

=RunTest( "2", 1000 ) && 2^2 = 4 spaces
=RunTest( "4", 1000 ) && 2^4 = 16 spaces
=RunTest( "8", 1000 ) && 2^8 = 256 spaces
=RunTest( "16", 1000 ) && 2^16 = 65,536 spaces
=RunTest( "20", 1000 ) && 2^20 spaces

RETURN
*************************************************************
FUNCTION RunTest

LPARAMETERS ;
	tcSpacesExponent ;
	, tnPasses

?"Spaces: 2^" + tcSpacesExponent ;
	+ "  Passes: " + LTRIM( STR( tnPasses ) ) ;
	+ "  Milliseconds: " + LTRIM( STR( Reduce_FoxTools( SPACE( EVALUATE( "2^" + tcSpacesExponent ) ), tnPasses ) ) ) ;
	+ "  (REDUCE in FoxTools.FLL)"

?"Spaces: 2^" + tcSpacesExponent ;
	+ "  Passes: " + LTRIM( STR( tnPasses ) ) ;
	+ "  Milliseconds: " + LTRIM( STR( Reduce_Successive( SPACE( EVALUATE( "2^" + tcSpacesExponent ) ), tnPasses ) ) ) ;
	+ "  (Reduce_Successive)"

?"Spaces: 2^" + tcSpacesExponent ;
	+ "  Passes: " + LTRIM( STR( tnPasses ) ) ;
	+ "  Milliseconds: " + LTRIM( STR( Reduce_Loop( SPACE( EVALUATE( "2^" + tcSpacesExponent ) ), tnPasses ) ) ) ;
	+ "  (Reduce_Loop)"

RETURN
*************************************************************
FUNCTION Reduce_FoxTools

LPARAMETERS ;
	tcString ;
	, tnPasses

LOCAL ;
	lnSeconds ;
	, lnIx

lnSeconds = SECONDS( )

FOR lnIx = 1 TO tnPasses STEP 1
	=REDUCE( tcString )

ENDFOR

RETURN ( SECONDS( ) - lnSeconds ) * 1000

ENDFUNC
*************************************************************
FUNCTION Reduce_Successive

LPARAMETERS ;
	tcString ;
	, tnPasses

LOCAL ;
	lnSeconds ;
	, lnIx

lnSeconds = SECONDS( )

FOR lnIx = 1 TO tnPasses STEP 1
	* Code below handles spaces up to 2^20 long (fails on 2^20 + 1)

	tcString = STRTRAN( tcString, [                ], [ ] )
	tcString = STRTRAN( tcString, [                ], [ ] )
	tcString = STRTRAN( tcString, [        ], [ ] )
	tcString = STRTRAN( tcString, [        ], [ ] )
	tcString = STRTRAN( tcString, [    ], [ ] )
	tcString = STRTRAN( tcString, [    ], [ ] )
	tcString = STRTRAN( tcString, [  ], [ ] )
	tcString = STRTRAN( tcString, [  ], [ ] )

ENDFOR

RETURN ( SECONDS( ) - lnSeconds ) * 1000

ENDFUNC
*************************************************************
FUNCTION Reduce_Loop

LPARAMETERS ;
	tcString ;
	, tnPasses

LOCAL ;
	lnSeconds ;
	, lnIx

lnSeconds = SECONDS( )

FOR lnIx = 1 TO tnPasses STEP 1
	DO WHILE [  ] $ tcString
		tcString = STRTRAN( tcString, [  ], [ ] )

	ENDDO
	
ENDFOR

RETURN ( SECONDS( ) - lnSeconds ) * 1000

ENDFUNC
*************************************************************
Results on my old Athlon/1000 machine:
Spaces: 2^2  Passes: 1000  Milliseconds: 17  (REDUCE in FoxTools.FLL)  
Spaces: 2^2  Passes: 1000  Milliseconds: 13  (Reduce_Successive)  
Spaces: 2^2  Passes: 1000  Milliseconds: 1  (Reduce_Loop) 
Spaces: 2^4  Passes: 1000  Milliseconds: 17  (REDUCE in FoxTools.FLL)  
Spaces: 2^4  Passes: 1000  Milliseconds: 13  (Reduce_Successive)  
Spaces: 2^4  Passes: 1000  Milliseconds: 1  (Reduce_Loop) 
Spaces: 2^8  Passes: 1000  Milliseconds: 32  (REDUCE in FoxTools.FLL)  
Spaces: 2^8  Passes: 1000  Milliseconds: 13  (Reduce_Successive)  
Spaces: 2^8  Passes: 1000  Milliseconds: 2  (Reduce_Loop) 
Spaces: 2^16  Passes: 1000  Milliseconds: 4213  (REDUCE in FoxTools.FLL)   
Spaces: 2^16  Passes: 1000  Milliseconds: 15  (Reduce_Successive)  
Spaces: 2^16  Passes: 1000  Milliseconds: 18  (Reduce_Loop)  
Spaces: 2^20  Passes: 1000  Milliseconds: 87342  (REDUCE in FoxTools.FLL)   
Spaces: 2^20  Passes: 1000  Milliseconds: 45  (Reduce_Successive)  
Spaces: 2^20  Passes: 1000  Milliseconds: 295  (Reduce_Loop)
Your technique is by far the fastest for small numbers of spaces. Mine matches yours at 65,536 spaces and is much faster with larger numbers of sequential spaces.

Interestingly, the FoxTools REDUCE function is the big loser in all these tests.
Regards. Al

"Violence is the last refuge of the incompetent." -- Isaac Asimov
"Never let your sense of morals prevent you from doing what is right." -- Isaac Asimov

Neither a despot, nor a doormat, be

Every app wants to be a database app when it grows up
Précédent
Suivant
Répondre
Fil
Voir

Click here to load this message in the networking platform