这是对可变列数的另一种尝试。给定这个数组:
animals = [
['Cats', 'Dogs', 'Fish'],
['Mr. Tinkles', 'Buddy', 'Nemo'],
['Calico', 'Butch', 'Marlin'],
['Ginger', 'Ivy', 'Dory']
]
我们可以通过transpose、map、length和max来计算每一列的宽度:
widths = animals.transpose.map { |x| x.map(&:length).max }
#=> [11, 5, 6]
基于此,我们可以生成一个可以传递给sprintf(或其快捷方式%)的格式字符串:
row_format = widths.map { |w| "%-#{w}s" }.join(' ')
#=> "%-11s %-5s %-6s"
%s 表示字符串参数,11、5 和 6 是我们的宽度,- 左对齐结果。
让我们试试吧:
row_format % animals[0] #=> "Cats Dogs Fish "
row_format % animals[1] #=> "Mr. Tinkles Buddy Nemo "
row_format % animals[2] #=> "Calico Butch Marlin"
看起来不错,我们应该使用循环并将所有内容包装在一个方法中:
def print_table(array)
widths = array.transpose.map { |x| x.map(&:length).max }
row_format = widths.map { |w| "%-#{w}s" }.join(' ')
array.each do |row_values|
puts row_format % row_values
end
end
print_table(animals)
输出:
Cats Dogs Fish
Mr. Tinkles Buddy Nemo
Calico Butch Marlin
Ginger Ivy Dory
更复杂的格式
稍微调整一下,也可以输出一个 MySQL 样式表:
def print_mysql_table(array)
widths = array.transpose.map { |x| x.map(&:length).max }
row_format = '|%s|' % widths.map { |w| " %-#{w}s " }.join('|')
separator = '+%s+' % widths.map { |w| '-' * (w+2) }.join('+')
header, *rows = array
puts separator
puts row_format % header
puts separator
rows.each do |row_values|
puts row_format % row_values
end
puts separator
end
print_mysql_table(animals)
输出:
+-------------+-------+--------+
| Cats | Dogs | Fish |
+-------------+-------+--------+
| Mr. Tinkles | Buddy | Nemo |
| Calico | Butch | Marlin |
| Ginger | Ivy | Dory |
+-------------+-------+--------+