Align columns of numbers by decimal point

For the Compleat Fan
Locked
cormullion
Posts: 2038
Joined: Tue Nov 29, 2005 8:28 pm
Location: latiitude 50N longitude 3W
Contact:

Align columns of numbers by decimal point

Post by cormullion »

Is there a clever way to align numbers by the decimal point when using the println and format functions?

Code: Select all

 205.492  
 201.729  
 201.38   
  -5.38672
  -1.38724
-158.966  
 123.63   
Or do I convert them to strings first, then calculate the amount of leading and trailing spaces to use?

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

format is used for this:

Code: Select all

> (map (fn (num) (format "%10.2f" num)) '(1.22 123.456 12345.567))
("      1.22" "    123.46" "  12345.57")
> 
The 10 tells the format spec to make the whole field 10 positions long. This includes the decimal point and all leading spaces. The 2 tells it to format for 2 decimals begind the point. As you can see in the example, it also rounds numbers.

This works only when all numbers are formatted for the same amount of decimals after the point. In your case you could make a strings with a high count after the decimal count:

Code: Select all

> (map (fn (num) (format "%10.5f" num)) '(1.2 123.45 12345.567))
("   1.20000" " 123.45000" "12345.56700")
> 
... and than replace trailing 0's in those strings with some clever regular expression ;)

Lutz

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

.... like this:

Code: Select all

> (replace {(0+)$} "12345.567000" (dup " " (length $1)) 0)
"12345.567   "
> 
the pattern {(0+)$} finds one or more trailing zeros and replaces them with the same number of spaces. Putting it all together:

Code: Select all

(map (fn (num) (replace {(0+)$} 
                          (format "%12.5f" num) 
                          (dup " " (length $1)) 0) ) 
          '(1.2 123.45 12345.567))
=>("     1.2    " "   123.45   " " 12345.567  ")
Lutz

cormullion
Posts: 2038
Joined: Tue Nov 29, 2005 8:28 pm
Location: latiitude 50N longitude 3W
Contact:

Post by cormullion »

Of course - now I see you do it it looks natural. For some reason I hadn't thought of trying to capture the results of format and continuing to work on them, I've just been using format in print statements.

Thanks Lutz!

cormullion
Posts: 2038
Joined: Tue Nov 29, 2005 8:28 pm
Location: latiitude 50N longitude 3W
Contact:

Post by cormullion »

I ended up using this:

Code: Select all

(replace {(0+)[^0-9|.]} temp (dup " " (length $1)) 0)
hoping to strip 0's if not followed by more digits or decimal point. How long did it take for you guys to become blackbelts in RegExp-Do? :-) Takes me an hour per regex...

m i c h a e l
Posts: 394
Joined: Wed Apr 26, 2006 3:37 am
Location: Oregon, USA
Contact:

Post by m i c h a e l »

I only have my yellow belt in regex, so I'm around the same level as you, cormullion.

I remember a quote having to do with someone having a problem that he decided to solve with regular expressions. "Now," as the saying goes, "he has two problems." ;-)

m i c h a e l

Locked