1. Computing

CSV Example: Format Strings and Printing the ASCII Table


You can see the complete code that goes along with this article here, or download a zip file.

This part might need some explanation, as format strings aren't often used in Ruby. Format strings are going to be more familiar to C or perhaps Python programmers, but as Ruby has such good string interpolation that format strings are rarely needed. However, for formatting tabular data, format strings are very handy. This is what they were designed for, after all.

A format string is a string with placeholders which will be filled with values at a later time. For example, the string "%s:%d" contains two placeholders. The first is a string placeholder, and the second is a decimal number. However, it gets a bit more useful than that. In between the percent sign and the letter, you can use a number of parameters that will define how the value will be formatted. In this program, we'll be using the width parameter with left justification. To define this, we say "%-10s". The minus here is not negative, it's saying to left-justify the string. The number here is the number of characters to use for the value. If the value is not long enough, it will be padded with spaces. If it's too long, it will be truncated. This is very useful in printing tabular data.

To form the format string, we'll use some string interpolation. That sounds a bit odd, forming an archaic form of string interpolation using string interpolation, but it gets the job done. Again, we'll be using the Enumerable#map method to map each column to "%-Xs", where X is the column width we calculated earlier. We'll then be joining all those placeholders together with the string " | ", which has no special meaning but will provide nice lines for the table.

# Make the format string
format = columns.map{|c| "%-#{column_widths[c]}s" }.join(' | ')

Printing the Table

Printing the table is rather straightforward. For the most part, we're just using the string format operator %, which puts values into format string placeholders and the map method. First, we print the column names. It can't get much simpler.

puts format % columns

The next line is a bit of a hack and only there to make the table a bit more pretty. Sally Schoolteacher wants a line printed under the header so it looks nice. We can do that, and a bit more. Where the vertical lines between the columns join with this horizontal lines, we'll use + symbols to represent two lines intersecting.

As was said, how this is done here is a bit of a hack. The format string itself is modified to replace the " | " separators with "-+-" separators. This is done using the String#tr method. The tr (or "translate") method takes two strings as arguments. In the target string, it will search for characters from the first string and replace them with corresponding characters from the second string. In other words, the two strings act as a translation table.

We then format it with the column widths mapped to '-' * X where X is the column width. In other words, for each column, make a string of dash characters as wide as the column. Then push it into the format string, as we'll get a nice separator line.

puts format.tr(' |', '-+') % column_widths.values.map{|v| '-'*v }

Finally, we push each of the rows through the original format string. For each row, we map the column name array with the corresponding values from the grade hash. Doing it this way, we retrieve all of the values from the hash in the correct order. Then it's just pushed through the format string and voila, it's done!

grades.each do|g|
  puts format % columns.map{|c| g[c] }

If everything went right, you should be looking at a table like this one.

Name             | Art | History | Math | English | Science
Fredo Corleone   | 62  | 80      | 62   | 62      | 99     
Michael Corleone | 68  | 82      | 90   | 70      | 96     
Santino Corleone | 93  | 80      | 81   | 87      | 89     
Vito Corleone    | 87  | 85      | 72   | 65      | 70     
Tom Hagen        | 77  | 62      | 70   | 83      | 85   
  1. About.com
  2. Computing
  3. Ruby
  4. Beginning Ruby
  5. Strings
  6. Practical Examples
  7. CSV Example: Format Strings and Printing the ASCII Table

©2014 About.com. All rights reserved.