Ruby vs. Awk: An uneven match?

Thomas played around with Awk to pretty print LaTeX tables, resulting in a "one liner" ;-) . As I'm currently learning more Ruby, I was wondering if I could do better with Ruby. So here's the result. Decide for yourselves. :-)


awk -F '[\\t ]*([&]|\\\\\\\\)[\\t ]*' 'BEGIN { maxcol=0 } \
  { for (i=1; imaxcol) \
  maxcol=NF-1 } END { for (c=1; c<=maxcol; ++c) { \
  colwidth[c]=0; for (r=1;rcolwidth[c]) colwidth[c]= \
  length(cell[r,c]); }; for (r=1; r<=NR; ++r) { printf \
  "%s%"(colwidth[1]-length(cell[r,1]))"s", cell[r,1], ""; \
  for (c=2; c<=maxcol; ++c) printf " & %"colwidth[c]"s", \
  cell[r,c]; print " \\\\" } }'

Ruby: Full source available to play with.

# Splits the arrays contained in the strarr parameter into
# arrays containing the individual table cell contents.
def totable(strarr) do |line|
      line.gsub('\\','').split('&').map {|s| s.strip}

# Given a two multidimensional array of strings, this method
# returns an array with the maximum string sizes of the rows
# of the original array.
def rowwidths(tbl) {|x| {|y| y.size}}.map {|x| x.max}

# Given an Enumerable object containing LaTeX table source code
# lines, this method returns a pretty printed version of it (in
# one single string).
def prettyprint(strarr)
    tbl = totable(strarr)
    # transpose
    transposed = tbl.transpose
    colwidths = rowwidths(transposed)
    # on the transposed table: expand rows of strings
    # to full string size
    transposed = (0...transposed.size).map do |i|
      transposed[i].map {|x| sprintf("%#{colwidths[i]}s",x)}
    # transpose back
    tbl = transposed.transpose {|x| x.join(' & ') + " \\\n"}.join()

It's interesting to see where you end up when pushing closures to the limit to make code more concise. No explicit looping beyond that border. Is this the limit? Can you make the code more readable without going back to for-loops?