[ACCEPTED]-Nicely formatting output to console, specifying number of tabs-formatted

Accepted answer
Score: 58

Provided you know the maximum length to 3 be no more than 20 characters:

printf "%-20s %s\n", value_name, value

If you want 2 to make it more dynamic, something like 1 this should work nicely:

longest_key = data_hash.keys.max_by(&:length)
data_hash.each do |key, value|
  printf "%-#{longest_key.length}s %s\n", key, value
end
Score: 24

There is usually a %10s kind of printf scheme that 11 formats nicely.
However, I have not used 10 ruby at all, so you need to check that.


Yes, there 9 is printf with formatting.
The above example 8 should right align in a space of 10 chars.
You 7 can format based on your widest field in 6 the column.

printf ([port, ]format, arg...)

Prints 5 arguments formatted according to the format 4 like sprintf. If the first argument is the 3 instance of the IO or its subclass, print 2 redirected to that object. the default is 1 the value of $stdout.

Score: 21

String has a built-in ljust for exactly this:

x = {"foo"=>37, "something long"=>42, "between"=>99}
x.each { |k, v| puts "#{k.ljust(20)} #{v}" }
# Outputs:
#  foo                  37
#  something long       42
#  between              99

Or, if 3 you want tabs, you can do a little math 2 (assuming tab display width of 8) and write 1 a short display function:

def tab_pad(label, tab_stop = 4)
  label_tabs = label.length / 8
  label.ljust(label.length + tab_stop - label_tabs, "\t")
end

x.each { |k, v| puts "#{tab_pad(k)}#{v}" }
# Outputs: 
#  foo                  37
#  something long       42
#  between              99
Score: 9

There was few bugs in it before, but now 2 you can use most of printf syntax with % operator:

1.9.3-p194 :025 > " %-20s %05d" % ['hello', 12]
 => " hello                00012" 

Of 1 course you can use precalculated width too:

1.9.3-p194 :030 > "%-#{width}s %05x" % ['hello', 12]
  => "hello          0000c" 
Score: 3

I wrote a thing

  • Automatically detects column widths
  • Spaces with spaces
  • Array of arrays [[],[],...] or array of hashes [{},{},...]
  • Does not detect columns too 4 wide for console window

    lists = [ [ 123, "SDLKFJSLDKFJSLDKFJLSDKJF" ], [ 123456, "ffff" ], ]

array_maxes

def array_maxes(lists)
  lists.reduce([]) do |maxes, list|
    list.each_with_index do |value, index|
      maxes[index] = [(maxes[index] || 0), value.to_s.length].max
    end
    maxes
  end
end

array_maxes(lists)
# => [6, 24]

puts_arrays_columns

def puts_arrays_columns(lists)
  maxes = array_maxes(hashes)
  lists.each do |list|
    list.each_with_index do |value, index|
      print " #{value.to_s.rjust(maxes[index])},"
    end
    puts
  end
end

puts_arrays_columns(lists)

# Output:
#     123, SDLKFJSLDKFJSLDKFJLSDKJF,
#  123456,                     ffff,

and 3 another thing

hashes = [
  { "id" => 123,    "name" => "SDLKFJSLDKFJSLDKFJLSDKJF" },
  { "id" => 123456, "name" => "ffff" },
]

hash_maxes

def hash_maxes(hashes)
  hashes.reduce({}) do |maxes, hash|
    hash.keys.each do |key|
      maxes[key] = [(maxes[key] || 0), key.to_s.length].max
      maxes[key] = [(maxes[key] || 0), hash[key].to_s.length].max
    end
    maxes
  end
end

hash_maxes(hashes)
# => {"id"=>6, "name"=>24}

puts_hashes_columns

def puts_hashes_columns(hashes)
  maxes = hash_maxes(hashes)

  return if hashes.empty?

  # Headers
  hashes.first.each do |key, value|
    print " #{key.to_s.rjust(maxes[key])},"
  end
  puts

  hashes.each do |hash|
    hash.each do |key, value|
      print " #{value.to_s.rjust(maxes[key])},"
    end
    puts
  end

end

puts_hashes_columns(hashes)

# Output:
#      id,                     name,
#     123, SDLKFJSLDKFJSLDKFJLSDKJF,
#  123456,                     ffff,

Edit: Fixes hash keys considered 2 in the length.

hashes = [
  { id: 123,    name: "DLKFJSDLKFJSLDKFJSDF", asdfasdf: :a  },
  { id: 123456, name: "ffff",                 asdfasdf: :ab },
]

hash_maxes(hashes)
# => {:id=>6, :name=>20, :asdfasdf=>8}

Want to whitelist columns 1 columns?

hashes.map{ |h| h.slice(:id, :name) }
# => [
#  { id: 123,    name: "DLKFJSDLKFJSLDKFJSDF" },
#  { id: 123456, name: "ffff"                 },
#]
Score: 1

For future reference and people who look 2 at this or find it... Use a gem. I suggest 1 https://github.com/wbailey/command_line_reporter

Score: 0

You typically don't want to use tabs, you 3 want to use spaces and essentially setup 2 your "columns" your self or else you run 1 into these types of problems.

More Related questions