如何打印具有固定列宽的2D数组

我有一个数组:

animals = [ ["cats", "dogs"], ["verrylongcat", "dog"], ["shortcat", "verrylongdog"], ["cat", "dog"] ] 

而且我想很好地展示它。 是否有一种简单的方法可以使柱子固定宽度,所以我得到这样的东西:

 cats dogs verrylongcat dog shortcat verrylongdog cat dog 

animals只是一个例子,我的arrays也可能有3列,4列甚至更多。

您正在寻找String#ljust

 max_cat_size = animals.map(&:first).max_by(&:size).size animals.each do |cat, dog| puts "#{cat.ljust(max_cat_size)} #{dog}" end 

如果您想要多个空格,只需在插值中添加相应的量即可。


假设你的arrays是n×m而不是2×m

 animal_max_sizes = animals.first.size.times.map do |index| animals.transpose[index].map(&:to_s).max_by(&:size).size end animals.map do |animal_line| animal_line.each.with_index.reduce('') do |animal_line, (animal, index)| animal_line + animal.to_s.ljust(animal_max_sizes[index].next) end end.each { |animal_line_stringified| puts animal_line_stringified } 

注意:如果您的数组包含nil ,数字等,则使用to_s es。

另一种方法是使用printf样式格式化。 如果您知道每行中总是只有2个单词,那么您可以这样做:

 #!/usr/bin/env ruby lines = [ ' cats dogs', ' verrylongcat dog', 'shortcat verrylongdog ', ' cat dog ', ] lines.map(&:strip).each do |line| puts "%-14s%s" % line.split end 

输出:

 cats dogs verrylongcat dog shortcat verrylongdog cat dog 

如果您需要根据数据计算列宽,那么您需要做更多的工作:

 # as @ndn showed: first_col_width = lines.map(&:split).map(&:first).max_by(&:size).size + 2 lines.map(&:strip).each do |line| puts "%-#{first_col_width}s%s" % line.split end 

这是另一种可变数量列的尝试。 给定这个数组:

 animals = [ ['Cats', 'Dogs', 'Fish'], ['Mr. Tinkles', 'Buddy', 'Nemo'], ['Calico', 'Butch', 'Marlin'], ['Ginger', 'Ivy', 'Dory'] ] 

我们可以通过transposemaplengthmax来计算每列的宽度:

 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表示字符串参数, 116是我们的宽度,并且-左对齐结果。

我们来试试吧:

 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 | +-------------+-------+--------+ 
Interesting Posts